diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,5 @@
+# Changelog for `time-units-types`
+
+## 0.1
+
+- First release
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2022 Michael B. Gale
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,29 @@
+# time-units-types
+
+This Haskell library exports types which can be used to describe simple type periods at the type-level. The type-level descriptions can then be reifed to corresponding values of the [`time-units`](https://hackage.haskell.org/package/time-units) library.
+
+```haskell
+{-# LANGUAGE TypeApplications #-}
+
+import Data.Time.TypeLevel
+
+type TenSeconds = Second 10
+
+main :: IO ()
+main = do
+    -- `durationVal` converts the type-level specification to a corresponding
+    -- value from "Data.Time.Units"
+    print $ durationVal @TenSeconds
+    -- `durationMicroseconds` converts the type-level specification to a
+    -- corresponding integer value, representing microseconds
+    print $ durationMicroseconds @TenSeconds
+```
+
+See the Haddock documentation for a reference of all supported units.
+
+## See also
+
+Related/similar projects:
+
+- [`time-units`](https://hackage.haskell.org/package/time-units)
+- [`o-clock`](https://hackage.haskell.org/package/o-clock)
diff --git a/src/Data/Time/TypeLevel.hs b/src/Data/Time/TypeLevel.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Time/TypeLevel.hs
@@ -0,0 +1,186 @@
+-------------------------------------------------------------------------------
+-- time-units-types
+-- Copyright 2022 Michael B. Gale (github@michael-gale.co.uk)
+-------------------------------------------------------------------------------
+
+{-# LANGUAGE AllowAmbiguousTypes #-}
+{-# LANGUAGE FlexibleContexts #-}
+
+-- | Exports types which can be used to describe time periods at
+-- the type-level. Use the `durationVal` function to reify them as the
+-- corresponding value-level descriptions from "Data.Time.Units" or the
+-- `durationMicroseconds` function to reify them as microseconds straight away.
+module Data.Time.TypeLevel (
+    KnownDuration(..),
+    durationMicroseconds,
+
+    Attosecond,
+    Femtosecond,
+    Picosecond,
+    Nanosecond,
+    Microsecond,
+    Millisecond,
+    Second,
+    Minute,
+    Hour,
+    Day,
+    Week,
+    Fortnight
+) where
+
+-------------------------------------------------------------------------------
+
+import GHC.TypeLits
+
+import Data.Time.Units qualified as Units
+import Data.Proxy
+import Data.Kind
+
+-------------------------------------------------------------------------------
+
+-- | Represents @n@-many attoseconds.
+data Attosecond (n :: Nat)
+
+-- | Represents @n@-many femtoseconds.
+data Femtosecond (n :: Nat)
+
+-- | Represents @n@-many picoseconds.
+data Picosecond (n :: Nat)
+
+-- | Represents @n@-many nanoseconds.
+data Nanosecond (n :: Nat)
+
+-- | Represents @n@-many microseconds.
+data Microsecond (n :: Nat)
+
+-- | Represents @n@-many milliseconds.
+data Millisecond (n :: Nat)
+
+-- | Represents @n@-many seconds.
+data Second (n :: Nat)
+
+-- | Represents @n@-many minutes.
+data Minute (n :: Nat)
+
+-- | Represents @n@-many hours.
+data Hour (n :: Nat)
+
+-- | Represents @n@-many days.
+data Day (n :: Nat)
+
+-- | Represents @n@-many weeks.
+data Week (n :: Nat)
+
+-- | Represents @n@-many fortnights.
+data Fortnight (n :: Nat)
+
+-- | A class of types which can be reified as value-level descriptions of
+-- time periods.
+class KnownDuration k where
+    -- | The type representing value-level descriptions of the time period
+    -- corresponding to @k@.
+    type DurationUnit k :: Type
+
+    -- | `durationVal` reifies the duration as the corresponding value-level
+    -- type. Intended to be used with @TypeApplications@.
+    --
+    -- >>> durationVal @(Second 10)
+    -- 10s :: Data.Time.Units.Second
+    durationVal :: DurationUnit k
+
+instance KnownNat n => KnownDuration (Attosecond n) where
+    type DurationUnit (Attosecond n) = Units.Attosecond
+
+    durationVal =
+        fromInteger @Units.Attosecond $
+        natVal (Proxy :: Proxy n)
+
+-- | `durationMicroseconds` is a convenience function which reifies a
+-- type-level duration as microseconds on the value level. Intended to be
+-- used with @TypeApplications@.
+--
+-- >>> durationMicroseconds @(Second 10)
+-- 10000000 :: Integer
+durationMicroseconds
+    :: forall d . (KnownDuration d, Units.TimeUnit (DurationUnit d))
+    => Integer
+durationMicroseconds = Units.toMicroseconds $ durationVal @d
+
+instance KnownNat n => KnownDuration (Femtosecond n) where
+    type DurationUnit (Femtosecond n) = Units.Femtosecond
+
+    durationVal =
+        fromInteger @Units.Femtosecond $
+        natVal (Proxy :: Proxy n)
+
+instance KnownNat n => KnownDuration (Picosecond n) where
+    type DurationUnit (Picosecond n) = Units.Picosecond
+
+    durationVal =
+        fromInteger @Units.Picosecond $
+        natVal (Proxy :: Proxy n)
+
+instance KnownNat n => KnownDuration (Nanosecond n) where
+    type DurationUnit (Nanosecond n) = Units.Nanosecond
+
+    durationVal =
+        fromInteger @Units.Nanosecond $
+        natVal (Proxy :: Proxy n)
+
+instance KnownNat n => KnownDuration (Microsecond n) where
+    type DurationUnit (Microsecond n) = Units.Microsecond
+
+    durationVal =
+        fromInteger @Units.Microsecond $
+        natVal (Proxy :: Proxy n)
+
+instance KnownNat n => KnownDuration (Millisecond n) where
+    type DurationUnit (Millisecond n) = Units.Millisecond
+
+    durationVal =
+        fromInteger @Units.Millisecond $
+        natVal (Proxy :: Proxy n)
+
+instance KnownNat n => KnownDuration (Second n) where
+    type DurationUnit (Second n) = Units.Second
+
+    durationVal =
+        fromInteger @Units.Second $
+        natVal (Proxy :: Proxy n)
+
+instance KnownNat n => KnownDuration (Minute n) where
+    type DurationUnit (Minute n) = Units.Minute
+
+    durationVal =
+        fromInteger @Units.Minute $
+        natVal (Proxy :: Proxy n)
+
+instance KnownNat n => KnownDuration (Hour n) where
+    type DurationUnit (Hour n) = Units.Hour
+
+    durationVal =
+        fromInteger @Units.Hour $
+        natVal (Proxy :: Proxy n)
+
+instance KnownNat n => KnownDuration (Day n) where
+    type DurationUnit (Day n) = Units.Day
+
+    durationVal =
+        fromInteger @Units.Day $
+        natVal (Proxy :: Proxy n)
+
+instance KnownNat n => KnownDuration (Week n) where
+    type DurationUnit (Week n) = Units.Week
+
+    durationVal =
+        fromInteger @Units.Week $
+        natVal (Proxy :: Proxy n)
+
+instance KnownNat n => KnownDuration (Fortnight n) where
+    type DurationUnit (Fortnight n) = Units.Fortnight
+
+    durationVal =
+        fromInteger @Units.Fortnight $
+        natVal (Proxy :: Proxy n)
+
+-------------------------------------------------------------------------------
diff --git a/time-units-types.cabal b/time-units-types.cabal
new file mode 100644
--- /dev/null
+++ b/time-units-types.cabal
@@ -0,0 +1,52 @@
+cabal-version: 1.12
+
+-- This file has been generated from package.yaml by hpack version 0.34.4.
+--
+-- see: https://github.com/sol/hpack
+
+name:           time-units-types
+version:        0.1.0.0
+synopsis:       Type-level representations of time durations.
+description:    Please see the README on GitHub at <https://github.com/mbg/time-units-types#readme>
+category:       Data
+homepage:       https://github.com/mbg/time-units-types#readme
+bug-reports:    https://github.com/mbg/time-units-types/issues
+author:         Michael B. Gale
+maintainer:     github@michael-gale.co.uk
+copyright:      2022 Michael B. Gale
+license:        MIT
+license-file:   LICENSE
+build-type:     Simple
+extra-source-files:
+    README.md
+    ChangeLog.md
+
+source-repository head
+  type: git
+  location: https://github.com/mbg/time-units-types
+
+library
+  exposed-modules:
+      Data.Time.TypeLevel
+  other-modules:
+      Paths_time_units_types
+  hs-source-dirs:
+      src
+  default-extensions:
+      DataKinds
+      FlexibleInstances
+      FunctionalDependencies
+      ImportQualifiedPost
+      KindSignatures
+      MultiParamTypeClasses
+      PolyKinds
+      ScopedTypeVariables
+      StandaloneKindSignatures
+      TypeApplications
+      TypeFamilies
+      TypeOperators
+  ghc-options: -Wall
+  build-depends:
+      base >=4.7 && <5
+    , time-units
+  default-language: Haskell2010
