diff --git a/chronos.cabal b/chronos.cabal
--- a/chronos.cabal
+++ b/chronos.cabal
@@ -1,5 +1,5 @@
 name: chronos
-version: 1.0.1
+version: 1.0.2
 synopsis: A performant time library
 description:
   Performance-oriented time library for haskell. The main differences
@@ -48,10 +48,7 @@
     , text >= 1.2 && < 1.3
     , bytestring >= 0.10 && < 0.11
     , attoparsec >= 0.13 && < 0.14
-    -- Remove support for aeson < 1.0 after the newer
-    -- aeson lands in stackage. Currently, ToJSONKey
-    -- and FromJSONKey instances cannot be added.
-    , aeson >= 0.11 && < 1.3
+    , aeson >= 1.1 && < 1.3
     , hashable >= 1.2 && < 1.3
     , primitive >= 0.6 && < 0.7
     , torsor >= 0.1 && < 0.2
diff --git a/src/Chronos.hs b/src/Chronos.hs
--- a/src/Chronos.hs
+++ b/src/Chronos.hs
@@ -147,14 +147,21 @@
   , builder_YmdIMS_p_z
   , builder_DmyIMS_p_z
   , builderW3Cz
-  , builderOffset
-  , parserOffset
     -- *** UTF-8 ByteString
   , builderUtf8_YmdHMSz
   , parserUtf8_YmdHMSz
   , builderUtf8_YmdIMS_p_z
   , builderUtf8W3Cz
+    -- ** Offset
+    -- *** Text
+  , encodeOffset
+  , builderOffset
+  , decodeOffset
+  , parserOffset
+    -- *** UTF-8 ByteString
+  , encodeOffsetUtf8
   , builderOffsetUtf8
+  , decodeOffsetUtf8
   , parserOffsetUtf8
     -- ** Timespan
     -- *** Text
@@ -204,12 +211,15 @@
 import Data.Word (Word64)
 import Torsor
 import GHC.Generics (Generic)
-import Data.Aeson (FromJSON,ToJSON)
+import Data.Aeson (FromJSON,ToJSON,FromJSONKey,ToJSONKey)
 import Data.Primitive
 import Foreign.Storable
 import Data.Hashable (Hashable)
 import Control.Exception (evaluate)
 import qualified System.Clock as CLK
+import qualified Data.Aeson as AE
+import qualified Data.Aeson.Encoding as AEE
+import qualified Data.Aeson.Types as AET
 import qualified Data.Text as Text
 import qualified Data.Text.Read as Text
 import qualified Data.Attoparsec.Text as AT
@@ -558,7 +568,10 @@
 internalMatchMonth :: MonthMatch a -> Month -> a
 internalMatchMonth (MonthMatch v) (Month ix) = Vector.unsafeIndex v (fromIntegral ix)
 
-daysInMonth :: Bool -> Month -> Int
+daysInMonth ::
+     Bool -- ^ Is this a leap year?
+  -> Month -- ^ Month of year
+  -> Int
 daysInMonth isLeap m = if isLeap
   then internalMatchMonth leapYearMonthLength m
   else internalMatchMonth normalYearMonthLength m
@@ -1305,6 +1318,9 @@
   SubsecondPrecisionAuto
   (DatetimeFormat (Just '-') (Just 'T') (Just ':'))
 
+encodeOffset :: OffsetFormat -> Offset -> Text
+encodeOffset fmt = LT.toStrict . TB.toLazyText . builderOffset fmt
+
 builderOffset :: OffsetFormat -> Offset -> TB.Builder
 builderOffset x = case x of
   OffsetFormatColonOff -> builderOffset_z
@@ -1312,6 +1328,10 @@
   OffsetFormatSecondsPrecision -> builderOffset_z2
   OffsetFormatColonAuto -> builderOffset_z3
 
+decodeOffset :: OffsetFormat -> Text -> Maybe Offset
+decodeOffset fmt =
+  either (const Nothing) Just . AT.parseOnly (parserOffset fmt <* AT.endOfInput)
+
 parserOffset :: OffsetFormat -> Parser Offset
 parserOffset x = case x of
   OffsetFormatColonOff -> parserOffset_z
@@ -1443,6 +1463,13 @@
   SubsecondPrecisionAuto
   (DatetimeFormat (Just '-') (Just 'T') (Just ':'))
 
+encodeOffsetUtf8 :: OffsetFormat -> Offset -> ByteString
+encodeOffsetUtf8 fmt = LB.toStrict . BB.toLazyByteString . builderOffsetUtf8 fmt
+
+decodeOffsetUtf8 :: OffsetFormat -> ByteString -> Maybe Offset
+decodeOffsetUtf8 fmt =
+  either (const Nothing) Just . AB.parseOnly (parserOffsetUtf8 fmt)
+
 builderOffsetUtf8 :: OffsetFormat -> Offset -> BB.Builder
 builderOffsetUtf8 x = case x of
   OffsetFormatColonOff -> builderOffsetUtf8_z
@@ -1749,6 +1776,17 @@
 newtype Month = Month { getMonth :: Int }
   deriving (Show,Read,Eq,Ord,Prim)
 
+instance Enum Month where
+  fromEnum = getMonth
+  toEnum = Month
+  succ (Month x) = if x < 11
+    then Month (x + 1)
+    else error "Enum.succ{Month}: tried to take succ of December"
+  pred (Month x) = if x > 0
+    then Month (x - 1)
+    else error "Enum.pred{Month}: tried to take succ of January"
+  enumFrom x = enumFromTo x (Month 11)
+
 instance Bounded Month where
   minBound = Month 0
   maxBound = Month 11
@@ -2016,4 +2054,28 @@
 instance Enum OrdinalDate where
   fromEnum d = fromEnum (ordinalDateToDay d)
   toEnum i = dayToOrdinalDate (toEnum i)
+
+instance ToJSON Datetime where
+  toJSON = AE.String . encode_YmdHMS SubsecondPrecisionAuto hyphen
+  toEncoding x = AEE.unsafeToEncoding (BB.char7 '"' <> builderUtf8_YmdHMS SubsecondPrecisionAuto hyphen x <> BB.char7 '"')
+
+instance ToJSON Offset where
+  toJSON = AE.String . encodeOffset OffsetFormatColonOn
+  toEncoding x = AEE.unsafeToEncoding (BB.char7 '"' <> builderOffsetUtf8 OffsetFormatColonOn x <> BB.char7 '"')
+
+instance FromJSON Offset where
+  parseJSON = AE.withText "Offset" aesonParserOffset
+
+instance ToJSONKey Offset where
+  toJSONKey = AE.ToJSONKeyText
+    (encodeOffset OffsetFormatColonOn)
+    (\x -> AEE.unsafeToEncoding (BB.char7 '"' <> builderOffsetUtf8 OffsetFormatColonOn x <> BB.char7 '"'))
+
+instance FromJSONKey Offset where
+  fromJSONKey = AE.FromJSONKeyTextParser aesonParserOffset
+
+aesonParserOffset :: Text -> AET.Parser Offset
+aesonParserOffset t = case decodeOffset OffsetFormatColonOn t of
+  Nothing -> fail "could not parse Offset"
+  Just x -> return x
 
