diff --git a/formatting.cabal b/formatting.cabal
--- a/formatting.cabal
+++ b/formatting.cabal
@@ -1,5 +1,5 @@
 name:                formatting
-version:             3.1.0
+version:             3.1.1
 synopsis:            Combinator-based type-safe formatting (like printf() or FORMAT)
 description:         Combinator-based type-safe formatting (like printf() or FORMAT), modelled from the HoleyMonoids package.
 license:             BSD3
diff --git a/src/Formatting.hs b/src/Formatting.hs
--- a/src/Formatting.hs
+++ b/src/Formatting.hs
@@ -31,27 +31,6 @@
   module Formatting.Formatters
  ) where
 
-import           Formatting.Holey
-import           Formatting.Formatters
-
-import           Data.Text.Lazy (Text)
-import           Data.Text.Lazy.Builder (Builder)
-import qualified Data.Text.Lazy.Builder as T
-import qualified Data.Text.Lazy.IO      as T
-import           System.IO
-
--- | Run the formatter and return a "Text" value.
-format :: Holey Builder Text a -> a
-format m = runHM m T.toLazyText
-
--- | Run the formatter and return a "Builder" value.
-bprint :: Holey Builder Builder a -> a
-bprint m = runHM m id
-
--- | Run the formatter and print out the text to stdout.
-fprint :: Holey Builder (IO ()) a -> a
-fprint m = runHM m (T.putStr . T.toLazyText)
-
--- | Run the formatter and put the output onto the given "Handle".
-hprint :: Handle -> Holey Builder (IO ()) a -> a
-hprint h m = runHM m (T.hPutStr h . T.toLazyText)
+import Formatting.Formatters
+import Formatting.Holey
+import Formatting.Internal
diff --git a/src/Formatting/Formatters.hs b/src/Formatting/Formatters.hs
--- a/src/Formatting/Formatters.hs
+++ b/src/Formatting/Formatters.hs
@@ -20,6 +20,7 @@
   stext,
   string,
   builder,
+  fconst,
   -- * Numbers
   int,
   float,
@@ -71,6 +72,10 @@
 -- | Build a builder.
 builder :: Format Builder
 builder = later id
+
+-- | Like `const` but for formatters.
+fconst :: Builder -> Format a
+fconst m = later (const m)
 
 -- | Build anything that implements the "Buildable" class.
 build :: Buildable a => Format a
diff --git a/src/Formatting/Time.hs b/src/Formatting/Time.hs
--- a/src/Formatting/Time.hs
+++ b/src/Formatting/Time.hs
@@ -1,14 +1,30 @@
+{-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE NoMonomorphismRestriction #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 -- | Formatters for time.
+--
+-- Example:
+--
+-- @
+-- REPL> before <- getCurrentTime
+-- REPL> after <- getCurrentTime
+-- REPL> format (hms % \" - \" % hms % \" = \" % diff False) before after (before,after)
+-- \"19:05:06 - 19:05:08 = 3 seconds\"
+-- REPL>
+-- @
+--
 
 module Formatting.Time where
 
+import           Data.List
+import           Data.Text.Lazy.Builder
+import           Formatting.Formatters  hiding (build)
 import           Formatting.Holey
+import           Formatting.Internal
 
-import           Data.Text (Text)
-import qualified Data.Text as T
+import           Data.Text              (Text)
+import qualified Data.Text              as T
 import           Data.Text.Buildable
 import           Data.Time
 import           System.Locale
@@ -194,6 +210,46 @@
 -- 'mondayStartWeek'), @00@ - @53@.
 weekOfYearMon :: FormatTime a => Format a
 weekOfYearMon = later (build . fmt "%W")
+
+-- | Display a time span as one time relative to another. Equiv. to
+-- (t1 - t2) for some (t1,t2) pair.
+diff :: Bool                      -- ^ Display 'in/ago'?
+     -> Format (UTCTime, UTCTime) -- ^ Example: '3 seconds ago', 'in three days'.
+diff fix =
+  later (fromLazyText . diffed)
+  where
+    diffed (t1,t2) =
+      case find (\(s,_,_) -> abs ts >= s) ranges of
+        Nothing -> "unknown"
+        Just (_,f,base) -> format (prefix % f % suffix) (toInt ts base)
+      where ts = diffUTCTime t1 t2
+            prefix = now (if fix && ts > 0 then "in " else "")
+            suffix = now (if fix && ts < 0 then " ago" else "")
+    toInt ts base = abs (round (ts / base))
+    ranges =
+      [(0,int % " seconds",1)
+      ,(minute,fconst "a minute",0)
+      ,(minute*2,int % " minutes",minute)
+      ,(minute*30,fconst "half an hour",0)
+      ,(minute*31,int % " minutes",minute)
+      ,(hour,fconst "an hour",0)
+      ,(hour*2,int % " hours",hour)
+      ,(hour*3,fconst "a few hours",0)
+      ,(hour*4,int % " hours",hour)
+      ,(day,fconst "a day",0)
+      ,(day*2,int % " days",day)
+      ,(week,fconst "a week",0)
+      ,(week*2,int % " weeks",week)
+      ,(month,fconst "a month",0)
+      ,(month*2,int % " months",month)
+      ,(year,fconst "a year",0)
+      ,(year*2,int % " years",year)]
+      where year = month * 12
+            month = day * 30
+            week = day * 7
+            day = hour * 24
+            hour = minute * 60
+            minute = 60
 
 -- * Internal.
 
