diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,13 @@
+1.2.0 (2025-09-10)
+
+  * Added and adjusted some documentation
+  * Some subtle formatter changes
+  * Added str formatter for constant strings in log messages
+  * Pushed stackage snapshot up to lts-24.9
+  * Added timestamps to logging (via RichMessage/RichMsg)
+  * Added date formatting capability to the date formatters
+
+
 1.1.1 (2025-08-12)
 
   * Fixed incorrect API docs
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -20,9 +20,20 @@
 2. I've often wanted different colors for severities which is much easier with
    co-log than hslogger
 3. This library also includes some functions for formatting different parts of
-   a log message like the severity or the message itself. These are to be
-   composed together with the (%) and (%+) operators.
+   a log message like the severity, stack info, or the message itself. These
+   formatters can be composed together with the (%) and (%+) operators.
 
+Additionally:
+
+I found using the RichMsg/RichMessage types in co-log to be slightly on the
+complicated side to use. This library integrates timestamping through those
+types as well to make things easier while keeping the interface simple.
+
+co-log-simple uses the ISO8601 with zone offset format for timestamps by
+default which I like because it sorts. The time formatters in this library also
+support custom format strings as defined in the Data.Time.Format module in the
+base time library.
+
 For usage examples, see `src/examples/Main.hs` and the API docs for
 `Colog.Simple`
 
@@ -32,7 +43,8 @@
 Source code is available from Codeberg at the
 [co-log-simple](https://codeberg.org/dinofp/co-log-simple) project page.
 
-Generate Haddock docs during development if using stack:
+Handy command to generate Haddock docs during development if using stack. This
+constrains doc generation to modules in the library:
 
     $ stack haddock --haddock --no-haddock-deps
 
diff --git a/co-log-simple.cabal b/co-log-simple.cabal
--- a/co-log-simple.cabal
+++ b/co-log-simple.cabal
@@ -1,7 +1,7 @@
 cabal-version: 2.2
 
 name: co-log-simple
-version: 1.1.1
+version: 1.2.0
 synopsis: Simple enhancements for logging with co-log
 description: A library built upon co-log that makes constructing and using
   `LogAction`s simpler with some predefined formatters and a slightly enhanced
@@ -59,7 +59,7 @@
     -Wredundant-constraints
   build-depends:
       base >=3 && <5
-    , co-log >=0.6.0.2 && <0.7
+    , co-log >=0.7.0.0 && <0.8
 
 library
   import: lang
@@ -74,6 +74,7 @@
     , co-log-core >=0.3.2.1 && <0.4
     , mtl >=2.3.1 && <3
     , text >=2.0.2 && <2.2
+    , time >=1.4 && <1.14
 
 executable co-log-simple
   import: lang
diff --git a/src/examples/Main.hs b/src/examples/Main.hs
--- a/src/examples/Main.hs
+++ b/src/examples/Main.hs
@@ -4,15 +4,15 @@
   where
 
 import Colog.Monad (usingLoggerT)
-import Colog.Simple (LogAction, Message, Severity (Debug, Notice), (%), (%+),
-  logger, logInfo, logNotice, logTest, logTextStderr, logTextStdout, msg, msgc,
-  sevc, stack)
+import Colog.Simple (Severity (Debug, Notice), (%), (%+), logger,
+  loggingDisabled, logInfo, logNotice, logTest, logTextStderr, logTextStdout,
+  msg, msgc, sevc, stack, str, time)
 
 
 main :: IO ()
 main = do
   putStrLn "------------------------------------------"
-  usingLoggerT (logger (sevc % msg) logTextStdout Debug) $ do
+  usingLoggerT (logger (sevc %+ msg) logTextStdout Debug) $ do
     logNotice "Examples of all Severity values"
     logTest
 
@@ -28,11 +28,16 @@
     logTest
 
   putStrLn "------------------------------------------"
-  usingLoggerT (logger (sevc % msg %+ stack) logTextStdout Debug) $ do
+  usingLoggerT (logger (time %+ sevc %+ str "| " % msg) logTextStdout Debug) $ do
+    logNotice "Timestamps are often useful"
+    logTest
+
+  putStrLn "------------------------------------------"
+  usingLoggerT (logger (sevc %+ msg %+ stack) logTextStdout Debug) $ do
     logNotice "With call stack info"
     logTest
 
   putStrLn "------------------------------------------"
   -- Example of completely turning off logging
-  usingLoggerT (mempty :: LogAction IO Message) $
+  usingLoggerT loggingDisabled $
     logInfo "This message should never be shown"
diff --git a/src/lib/Colog/Simple.hs b/src/lib/Colog/Simple.hs
--- a/src/lib/Colog/Simple.hs
+++ b/src/lib/Colog/Simple.hs
@@ -2,11 +2,15 @@
 This module is for creating 'LogAction' instances that use the logging and
 formatting functions in this library.
 
+A simple example:
+
 @
 import Colog.Monad (usingLoggerT)
-import Colog.Simple (Severity (..), (%), logger, logNotice, logTextStdout, msg, sevc)
+import Colog.Simple (Severity (..), (%+), logger, logNotice, logTextStdout,
+  msg, sevc, time)
 
-usingLoggerT (logger (sevc % msg) logTextStdout Debug) $ logNotice "Take note of this!"
+usingLoggerT (logger (time %+ sevc %+ msg) logTextStdout Debug)
+  $ logNotice "Take note of this!"
 @
 
 The 'LogAction' produced by 'logger' above is what you would put in your
@@ -19,6 +23,7 @@
   (
     -- * Constructing LogAction loggers
     logger
+  , loggingDisabled
 
     -- * Utility functions
   , logTest
@@ -36,7 +41,8 @@
 
 import Colog (LogAction)
 import Colog.Actions (logTextStderr, logTextStdout)
-import Colog.Message (formatWith)
+import Colog.Core.Action (cmapM)
+import Colog.Message (defaultFieldMap, upgradeMessageAction)
 import Colog.Monad (HasLog (..), WithLog)
 import Control.Monad.Trans (MonadIO)
 import Data.Text (Text)
@@ -47,11 +53,19 @@
 
 -- | Construct a logging action
 logger :: MonadIO m
-  => (Message -> Text)  -- ^ Format function
+  => (RichMessage m -> m Text)  -- ^ Format function
   -> LogAction m Text   -- ^ Where log message output will go
   -> Severity           -- ^ The severity level to filter at or above
   -> LogAction m Message
-logger fmtFs targetAction sev' = setSeverity sev' . formatWith fmtFs $ targetAction
+logger fmtFs targetAction sev'
+  = setSeverity sev'
+  . upgradeMessageAction defaultFieldMap
+  $ cmapM fmtFs targetAction
+
+
+-- | Use this to completely disable logging
+loggingDisabled :: Applicative m => LogAction m Message
+loggingDisabled = mempty
 
 
 -- | Test function to generate messages with every severity in this library
diff --git a/src/lib/Colog/Simple/Message.hs b/src/lib/Colog/Simple/Message.hs
--- a/src/lib/Colog/Simple/Message.hs
+++ b/src/lib/Colog/Simple/Message.hs
@@ -1,32 +1,42 @@
 {-|
 The workhorse module of this library. Here you will find types for working with
 this logging library along with functions for issuing log messages of various
-severities. Also in this module are a small set of basic log output formatters.
+severities. Also in this module are log output formatters for different parts
+of a log message.
+
+The time* formatters use the local time and time zone as reported by the
+system. To change this to UTC or some other zone, use the TZ environment
+variable, timedatectl or similar and that zone will be used in logging.
+Example:
+
+@TZ=UTC my-app-with-logging@
 -}
 module Colog.Simple.Message
   (
     -- * Types
     Formatter
   , Message
+  , RichMessage
 
     -- * Functions for logging with a specific severity
   , logDebug, logInfo, logNotice, logWarning, logError
 
     -- * Functions for composing formatters
   , (%), (%+)
+  , str
 
     -- * Message formatting functions
-  , sev, sevc, stack, stackc, msg, msgc
+  , msg, msgc
+  , sev, sevc
+  , time, timec, timecf, timef
+  , stack, stackc
 
     -- * Other functions
   , colorize
   , setSeverity
 
     -- * Re-exported from ansi-terminal
-  , Color (..)
-
-    -- * Re-exported from co-log
-  , Msg (..)
+  , Color
 
     -- * Deprecated message formatting functions
   , basicFmt, colorFmt, colorSevFmt, colorSevStackFmt
@@ -34,9 +44,13 @@
   where
 
 import Colog (LogAction, cfilter)
-import Colog.Message (Msg (..), log, showSourceLoc)
+import Colog.Message (Msg (..), RichMsg (..), fmtRichMessageCustomDefault, log,
+  showSourceLoc)
 import Colog.Monad (WithLog)
+import Control.Monad.Trans (MonadIO, liftIO)
 import Data.Text (Text, pack)
+import Data.Time.Format (defaultTimeLocale, formatTime)
+import Data.Time.LocalTime (getCurrentTimeZone, utcToZonedTime)
 import GHC.Stack (withFrozenCallStack)
 import Prelude hiding (log)
 import System.Console.ANSI (Color (..), ColorIntensity (Vivid),
@@ -48,6 +62,7 @@
 -- | The type of a Msg parameterized with the custom severity type in this
 --   library
 type Message = Msg Severity
+type RichMessage m = RichMsg m Message
 
 
 -- | Log a message with 'Debug' severity
@@ -84,11 +99,11 @@
 
 
 showSeverity :: Severity -> Text
-showSeverity Debug    = "[Debug]   "
-showSeverity Info     = "[Info]    "
-showSeverity Notice   = "[Notice]  "
-showSeverity Warning  = "[Warning] "
-showSeverity Error    = "[Error]   "
+showSeverity Debug    = "[Debug]  "
+showSeverity Info     = "[Info]   "
+showSeverity Notice   = "[Notice] "
+showSeverity Warning  = "[Warning]"
+showSeverity Error    = "[Error]  "
 
 
 colorForSeverity :: Severity -> Color
@@ -100,50 +115,91 @@
 
 
 -- | The type of functions which format 'Message's into 'Text'
-type Formatter = Message -> Text
+type Formatter m = RichMessage m -> m Text
 
 
 -- | Apply two formatters to a 'Message' and combine the resulting 'Text's.
 --   With apologies to the formatting library for stealing their operator!
-(%) :: Formatter -> Formatter -> Formatter
-f % g = \msg' -> f msg' <> g msg'
+(%) :: MonadIO m => Formatter m -> Formatter m -> Formatter m
+f % g = \msg' -> (<>) <$> f msg' <*> g msg'
 
 
 -- | Apply two formatters to a 'Message' and combine the resulting 'Text'
 --   output with a space between.
 --   Again, with apologies to the formatting library for stealing their operator!
-(%+) :: Formatter -> Formatter -> Formatter
-f %+ g = f % const " " % g
+(%+) :: MonadIO m => Formatter m -> Formatter m -> Formatter m
+f %+ g = f % (const $ pure " ") % g
 
 
+-- | "Format" some text. Used to send some text to the logger. An example could
+--   be spacing between other formatters.
+str :: MonadIO m => Text -> RichMessage m -> m Text
+str = const . pure
+
+
+-- | Format the time the log message was generated
+time :: MonadIO m => RichMessage m -> m Text
+time = timef "%Y-%m-%dT%H:%M:%S%z"
+
+
+-- | Format the time the log message was generated with the supplied format
+--   string
+--
+--   For formatting docs see the Data.Time.Format module in the base time
+--   library.
+timef :: MonadIO m => String -> RichMessage m -> m Text
+timef timeFmt rm = do
+  zone <- liftIO $ getCurrentTimeZone
+  fmtRichMessageCustomDefault rm ( \_ mbTime _ ->
+    pack . maybe ""
+      (formatTime defaultTimeLocale timeFmt . utcToZonedTime zone)
+      $ mbTime )
+
+
+-- | Format the time the log message was generated with color based on the
+--   'Severity'
+timec :: MonadIO m => RichMessage m -> m Text
+timec rm@(RichMsg (Msg s _ _) _) = colorize (colorForSeverity s) <$> time rm
+
+
+-- | Format the time the log message was generated with color based on the
+--   'Severity' and with the supplied format string
+--
+--   For formatting docs see the Data.Time.Format module in the base time
+--   library.
+timecf :: MonadIO m => String -> RichMessage m -> m Text
+timecf timeFmt rm@(RichMsg (Msg s _ _) _) = colorize (colorForSeverity s)
+  <$> timef timeFmt rm
+
+
 -- | Format 'Severity'
-sev :: Message -> Text
-sev (Msg s _ _) = showSeverity s
+sev :: MonadIO m => RichMessage m -> m Text
+sev (RichMsg (Msg s _ _) _) = pure $ showSeverity s
 
 
 -- | Format 'Severity' with color based on the value
-sevc :: Message -> Text
-sevc (Msg s _ _) = colorize (colorForSeverity s) $ showSeverity s
+sevc :: MonadIO m => RichMessage m -> m Text
+sevc rm@(RichMsg (Msg s _ _) _) = colorize (colorForSeverity s) <$> sev rm
 
 
 -- | Format call stack info
-stack :: Message -> Text
-stack (Msg _ cs _) = showSourceLoc cs
+stack :: MonadIO m => RichMessage m -> m Text
+stack (RichMsg (Msg _ cs _) _) = pure $ showSourceLoc cs
 
 
 -- | Format call stack info with color based on the 'Severity'
-stackc :: Message -> Text
-stackc (Msg s cs _) = colorize (colorForSeverity s) $ showSourceLoc cs
+stackc :: MonadIO m => RichMessage m -> m Text
+stackc rm@(RichMsg (Msg s _ _) _) = colorize (colorForSeverity s) <$> stack rm
 
 
 -- | Format the log message
-msg :: Message -> Text
-msg (Msg _ _ m) = m
+msg :: MonadIO m => RichMessage m -> m Text
+msg (RichMsg (Msg _ _ m) _) = pure m
 
 
 -- | Format the log message with color based on the 'Severity'
-msgc :: Message -> Text
-msgc (Msg s _ m) = colorize (colorForSeverity s) m
+msgc :: MonadIO m => RichMessage m -> m Text
+msgc rm@(RichMsg (Msg s _ _) _)  = colorize (colorForSeverity s) <$> msg rm
 
 
 -- | Filter log messages for greater than or equal to the given 'Severity'
@@ -152,25 +208,25 @@
 
 
 -- | No color formatting. Just the message, no severity label
-basicFmt :: Message -> Text
+basicFmt :: MonadIO m => RichMessage m -> m Text
 basicFmt = msg
 {-# DEPRECATED basicFmt "Use msg instead" #-}
 
 
 -- | Format with no severity labels but message colors for each severity
-colorFmt :: Message -> Text
+colorFmt :: MonadIO m => RichMessage m -> m Text
 colorFmt = msgc
 {-# DEPRECATED colorFmt "Use msgc instead" #-}
 
 
 -- | Format with colored severity labels and no color for the message
-colorSevFmt :: Message -> Text
+colorSevFmt :: MonadIO m => RichMessage m -> m Text
 colorSevFmt = sevc % msg
 {-# DEPRECATED colorSevFmt "Use (sevc % msg) instead" #-}
 
 
 -- | Format with colored severity labels, call stack info, and no color for the
 --   message
-colorSevStackFmt :: Message -> Text
+colorSevStackFmt :: MonadIO m => RichMessage m -> m Text
 colorSevStackFmt = sevc % stack %+ msg
 {-# DEPRECATED colorSevStackFmt "Use (sevc % stack %+ msg) instead" #-}
diff --git a/stack.yaml b/stack.yaml
--- a/stack.yaml
+++ b/stack.yaml
@@ -1,4 +1,4 @@
-snapshot: lts-22.6
+snapshot: lts-24.9
 
 packages:
 - .
