diff --git a/chronos.cabal b/chronos.cabal
--- a/chronos.cabal
+++ b/chronos.cabal
@@ -1,6 +1,6 @@
 cabal-version: 3.0
 name: chronos
-version: 1.1.4
+version: 1.1.5
 synopsis: A high-performance time library
 description:
   Chronos is a performance-oriented time library for Haskell, with a
@@ -46,15 +46,15 @@
     -- it is OPTIONS_HADDOCK-hidden
       Chronos.Internal.CTimespec
   build-depends:
-    , aeson >= 1.1 && < 2.1
+    , aeson >= 1.1 && < 2.2
     , attoparsec >= 0.13 && < 0.15
-    , base >= 4.14 && < 4.16
+    , base >= 4.14 && < 4.18
     , bytestring >= 0.10 && < 0.12
     , deepseq >= 1.4.4.0
-    , hashable >= 1.2 && < 1.4
+    , hashable >= 1.2 && < 1.5
     , primitive >= 0.6.4 && < 0.8
-    , semigroups >= 0.16 && < 0.20
-    , text >= 1.2 && < 1.3
+    , semigroups >= 0.16 && < 0.21
+    , text >= 1.2 && < 1.3 || >= 2.0 && < 2.1
     , torsor >= 0.1 && < 0.2
     , vector >= 0.11 && < 0.13
     , bytebuild >= 0.3.8 && < 0.4
@@ -77,7 +77,7 @@
   build-depends:
     , HUnit
     , QuickCheck
-    , aeson >= 1.1 && < 1.6
+    , aeson >= 1.1 && < 2.2
     , attoparsec
     , base
     , bytestring
diff --git a/src/Chronos.hs b/src/Chronos.hs
--- a/src/Chronos.hs
+++ b/src/Chronos.hs
@@ -3,6 +3,7 @@
 {-# language DeriveGeneric #-}
 {-# language GeneralizedNewtypeDeriving #-}
 {-# language LambdaCase #-}
+{-# language MagicHash #-}
 {-# language MultiParamTypeClasses #-}
 {-# language NumericUnderscores #-}
 {-# language OverloadedStrings #-}
@@ -201,7 +202,9 @@
     -- *** UTF-8 Bytes
   , boundedBuilderUtf8BytesIso8601Zoneless
   , decodeUtf8BytesIso8601Zoneless
+  , decodeUtf8BytesIso8601ZonelessSpaced
     -- *** Short Text
+  , decodeShortTextIso8601Zulu
   , decodeShortTextIso8601Zoneless
   , encodeShortTextIso8601Zulu
   , encodeShortTextIso8601Zoneless
@@ -3364,7 +3367,20 @@
     , timePartsOffset = getOffset o
     }
 
--- | Decode an ISO-8601-encode datetime. The encoded time must not by suffixed
+-- | Decode an ISO-8601-encode datetime. The encoded time must be suffixed
+-- by either @Z@ or @+00:00@ or @+00@.
+decodeShortTextIso8601Zulu :: ShortText -> Maybe Chronos.Datetime
+decodeShortTextIso8601Zulu !t = BVP.parseBytesMaybe
+  ( do d <- parserUtf8BytesIso8601Zoneless 'T'
+       remaining <- BVP.remaining
+       case Bytes.length remaining of
+         1 | Bytes.unsafeIndex remaining 0 == 0x5A -> pure d
+         3 | Bytes.equalsCString (Ptr "+00"#) remaining -> pure d
+         6 | Bytes.equalsCString (Ptr "+00:00"#) remaining -> pure d
+         _ -> BVP.fail ()
+  ) (Bytes.fromShortByteString (TS.toShortByteString t))
+
+-- | Decode an ISO-8601-encode datetime. The encoded time must not be suffixed
 -- by an offset. Any offset (e.g. @-05:00@, @+00:00@, @Z@) will cause a decode
 -- failure.
 decodeShortTextIso8601Zoneless :: ShortText -> Maybe Chronos.Datetime
@@ -3377,17 +3393,25 @@
 decodeShortTextIso8601 !t = decodeUtf8BytesIso8601
   (Bytes.fromShortByteString (TS.toShortByteString t))
 
+-- | Decode an ISO-8601-encode datetime.
 decodeUtf8BytesIso8601Zoneless :: Bytes -> Maybe Chronos.Datetime
 decodeUtf8BytesIso8601Zoneless !b =
-  BVP.parseBytesMaybe (parserUtf8BytesIso8601Zoneless <* BVP.endOfInput ()) b
+  BVP.parseBytesMaybe (parserUtf8BytesIso8601Zoneless 'T' <* BVP.endOfInput ()) b
 
+-- | Decode a datetime that is nearly ISO-8601-encoded but uses a space
+-- instead of a T to separate the date and the time. For example:
+-- @2022-10-29 14:00:05@.
+decodeUtf8BytesIso8601ZonelessSpaced :: Bytes -> Maybe Chronos.Datetime
+decodeUtf8BytesIso8601ZonelessSpaced !b =
+  BVP.parseBytesMaybe (parserUtf8BytesIso8601Zoneless ' ' <* BVP.endOfInput ()) b
+
 decodeUtf8BytesIso8601 :: Bytes -> Maybe Chronos.OffsetDatetime
 decodeUtf8BytesIso8601 !b =
   BVP.parseBytesMaybe (parserUtf8BytesIso8601 <* BVP.endOfInput ()) b
 
-parserUtf8BytesIso8601Zoneless :: BVP.Parser () s Chronos.Datetime
+parserUtf8BytesIso8601Zoneless :: Char -> BVP.Parser () s Chronos.Datetime
 {-# noinline parserUtf8BytesIso8601Zoneless #-}
-parserUtf8BytesIso8601Zoneless = do
+parserUtf8BytesIso8601Zoneless !sep = do
   year <- Latin.decWord ()
   Latin.char () '-'
   month' <- Latin.decWord ()
@@ -3400,7 +3424,7 @@
         (Chronos.Year (fromIntegral year))
         (Chronos.Month (fromIntegral month))
         (Chronos.DayOfMonth (fromIntegral dayWord))
-  Latin.char () 'T'
+  Latin.char () sep
   hourWord <- Latin.decWord8 ()
   when (hourWord > 23) (BVP.fail ())
   Latin.char () ':'
@@ -3436,7 +3460,7 @@
 parserUtf8BytesIso8601 :: BVP.Parser () s Chronos.OffsetDatetime
 {-# noinline parserUtf8BytesIso8601 #-}
 parserUtf8BytesIso8601 = do
-  dt <- parserUtf8BytesIso8601Zoneless
+  dt <- parserUtf8BytesIso8601Zoneless 'T'
   off <- Latin.any () >>= \case
     'Z' -> pure 0
     '+' -> parserBytesOffset
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -389,6 +389,18 @@
           (LText.toStrict . Builder.toLazyText . C.builder_YmdHMS (SubsecondPrecisionFixed 9) (DatetimeFormat Nothing Nothing Nothing))
           (either (const Nothing) Just . Atto.parseOnly (C.parser_YmdHMS (DatetimeFormat Nothing Nothing Nothing)))
       ]
+    , testProperty "ISO-8601 Roundtrip" $ propEncodeDecodeIso
+        C.encodeShortTextIso8601Zulu
+        (\input -> case C.decodeShortTextIso8601 input of
+          Just (OffsetDatetime dt (Offset 0)) -> Just dt
+          _ -> Nothing
+        )
+    , testProperty "ISO-8601 Zoneless Roundtrip" $ propEncodeDecodeIso
+        C.encodeShortTextIso8601Zoneless
+        (\input -> case C.decodeShortTextIso8601Zoneless input of
+          Just dt -> Just dt
+          _ -> Nothing
+        )
     ]
   , testGroup "Offset Datetime"
     [ testGroup "Builder Spec Tests" $
@@ -408,12 +420,6 @@
             either (const Nothing) Just $ flip Atto.parseOnly input $
               C.parser_YmdHMSz offsetFormat datetimeFormat
         )
-    , testProperty "ISO-8601 Roundtrip" $ propEncodeDecodeIso
-        C.encodeShortTextIso8601Zulu
-        (\input -> case C.decodeShortTextIso8601 input of
-          Just (OffsetDatetime dt (Offset 0)) -> Just dt
-          _ -> Nothing
-        )
     ]
   , testGroup "Posix Time"
     [ PH.testCase "Get now" $ do
@@ -491,6 +497,15 @@
       (C.timeToDayOfWeek (Time (-17308800000000000)) @?= DayOfWeek 6)
     , PH.testCase "Tuesday, June 6, 1944 4:00:00 PM"
       (C.timeToDayOfWeek (Time (-806918400000000000)) @?= DayOfWeek 2)
+    ]
+  , testGroup "timeToOffsetDatetime"
+    [ PH.testCase "EpochNeg4h"
+      (C.timeToOffsetDatetime (Offset (-240)) (Time 0) @?= OffsetDatetime
+        ( Datetime
+          ( Date (Year 1969) C.december (DayOfMonth 31) )
+          ( TimeOfDay 20 0 0 )
+        ) (Offset (-240))
+      )
     ]
   , testGroup "json"
     [ PH.testCase "Datetime" $
