diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,5 @@
+# Revision history for relevant-time
+
+## 0.1.0.0  -- YYYY-mm-dd
+
+* First version. Released on an unsuspecting world.
diff --git a/Data/RelevantTime.hs b/Data/RelevantTime.hs
new file mode 100644
--- /dev/null
+++ b/Data/RelevantTime.hs
@@ -0,0 +1,75 @@
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+{-# OPTIONS_GHC -Wall #-}
+
+module Data.RelevantTime
+  ( RelevantTime(..)
+  , encodeRelevantTime
+  , decodeRelevantTime
+  , absolutizeRelevantTime
+  ) where
+
+import Data.Text (Text)
+import Data.Aeson (ToJSON(..),FromJSON(..))
+import Data.Int (Int64)
+import Chronos.Types (Time)
+import Torsor (add,invert,scale)
+import qualified Chronos as CH
+import qualified Data.Text as T
+import qualified Data.Text.Read as TR
+import qualified Data.Aeson as AE
+
+data RelevantTime
+  = RelevantTimeMinute {-# UNPACK #-} !Int64
+  | RelevantTimeHour   {-# UNPACK #-} !Int64
+  | RelevantTimeDay    {-# UNPACK #-} !Int64
+  | RelevantTimeNow
+  | RelevantTimeMidnight
+  | RelevantTimeNoon
+  deriving (Eq,Show)
+
+instance ToJSON RelevantTime where
+  toJSON = AE.String . encodeRelevantTime
+
+instance FromJSON RelevantTime where
+  parseJSON = AE.withText "RelevantTime"
+    (maybe (fail "invalid RelevantTime") return . decodeRelevantTime)
+
+encodeRelevantTime :: RelevantTime -> Text
+encodeRelevantTime = \case
+  RelevantTimeNow -> "now"
+  RelevantTimeMidnight -> "midnight"
+  RelevantTimeNoon -> "noon"
+  RelevantTimeMinute x -> T.pack (show x ++ "m")
+  RelevantTimeHour x -> T.pack (show x ++ "h")
+  RelevantTimeDay x -> T.pack (show x ++ "d")
+
+decodeRelevantTime :: Text -> Maybe RelevantTime
+decodeRelevantTime t = if T.null t
+  then Nothing
+  else case t of
+    "now" -> Just RelevantTimeNow
+    "noon" -> Just RelevantTimeNoon
+    "midnight" -> Just RelevantTimeMidnight
+    _ -> case T.last t of
+      'm' -> RelevantTimeMinute <$> readInt (T.init t)
+      'h' -> RelevantTimeHour <$> readInt (T.init t)
+      'd' -> RelevantTimeDay <$> readInt (T.init t)
+      _ -> Nothing
+
+absolutizeRelevantTime :: Time -> RelevantTime -> Time
+absolutizeRelevantTime now x = case x of
+  RelevantTimeNow -> now
+  RelevantTimeNoon-> add (scale 12 CH.hour) (CH.dayToTimeMidnight (CH.timeToDayTruncate now))
+  RelevantTimeMidnight -> CH.dayToTimeMidnight (CH.timeToDayTruncate now)
+  RelevantTimeMinute n -> add (invert (scale n CH.minute)) now
+  RelevantTimeHour n -> add (invert (scale n CH.hour)) now
+  RelevantTimeDay n -> add (invert (scale n CH.day)) now
+
+readInt :: Text -> Maybe Int64
+readInt x = case TR.signed TR.decimal x of
+  Left _ -> Nothing
+  Right (i,leftover) -> if T.null leftover
+    then Just i
+    else Nothing
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2018, chessai
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of chessai nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/relevant-time.cabal b/relevant-time.cabal
new file mode 100644
--- /dev/null
+++ b/relevant-time.cabal
@@ -0,0 +1,26 @@
+name:                relevant-time
+version:             0.1.0.0
+synopsis:            humanised relevant time
+description:         Humans tend to think of time relative to a fixed point.
+                     This library offers a simple datatype, 'RelevantTime',
+                     which captures the logic behind that idea.
+homepage:            https://github.com/chessai/relevant-time.git
+license:             BSD3
+license-file:        LICENSE
+author:              Daniel Cartwright
+maintainer:          dcartwright@layer3com.com
+copyright:           copyright (c) Layer 3 Communications, Daniel Cartwright 
+category:            Data 
+build-type:          Simple
+extra-source-files:  ChangeLog.md
+cabal-version:       >=1.10
+
+library
+  exposed-modules:     Data.RelevantTime
+  other-extensions:    LambdaCase, OverloadedStrings
+  build-depends:       base >=4.7 && <5.0
+                     , aeson
+                     , chronos
+                     , text
+                     , torsor
+  default-language:    Haskell2010
