@@ -1,5 +1,5 @@
1−{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, IncoherentInstances,
1+{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, GeneralizedNewtypeDeriving,
2− OverlappingInstances, Rank2Types #-}
2+ IncoherentInstances, OverlappingInstances, Rank2Types #-}
4-- Module: Data.Aeson.Types
4-- Module: Data.Aeson.Types
5-- Copyright: (c) 2011 MailRank, Inc.
5-- Copyright: (c) 2011 MailRank, Inc.
@@ -19,6 +19,8 @@ module Data.Aeson.Types
21 , emptyObject
21 , emptyObject
22+ -- * Convenience types
22 -- * Type conversion
24 -- * Type conversion
24 , Result(..)
26 , Result(..)
@@ -46,7 +48,7 @@ import Data.Ratio (Ratio)
46import Data.Text (Text, pack, unpack)
48import Data.Text (Text, pack, unpack)
47import Data.Text.Encoding (decodeUtf8, encodeUtf8)
49import Data.Text.Encoding (decodeUtf8, encodeUtf8)
48import Data.Time.Clock (UTCTime)
50import Data.Time.Clock (UTCTime)
49−import Data.Time.Format (formatTime, parseTime)
51+import Data.Time.Format (FormatTime, formatTime, parseTime)
50import Data.Typeable (Typeable)
52import Data.Typeable (Typeable)
51import Data.Vector (Vector)
53import Data.Vector (Vector)
52import Data.Word (Word, Word8, Word16, Word32, Word64)
54import Data.Word (Word, Word8, Word16, Word32, Word64)
@@ -522,15 +524,31 @@ instance FromJSON Value where
522 parseJSON a = pure a
524 parseJSON a = pure a
523 {-# INLINE parseJSON #-}
525 {-# INLINE parseJSON #-}
525−-- We happen to use the same JSON formatting for a UTCTime as .NET
527+-- | A newtype wrapper for 'UTCTime' that uses the same non-standard
526−-- does for a DateTime. How handy!
528+-- serialization format as Microsoft .NET.
529+newtype DotNetTime = DotNetTime UTCTime
530+ deriving (Eq, Ord, Read, Show, Typeable, FormatTime)
532+instance ToJSON DotNetTime where
533+ toJSON (DotNetTime t) =
534+ String (pack (formatTime defaultTimeLocale "/Date(%s)/" t))
535+ {-# INLINE toJSON #-}
537+instance FromJSON DotNetTime where
538+ parseJSON (String t) =
539+ case parseTime defaultTimeLocale "/Date(%s)/" (unpack t) of
540+ Just d -> pure (DotNetTime d)
543+ {-# INLINE parseJSON #-}
527instance ToJSON UTCTime where
545instance ToJSON UTCTime where
528− toJSON t = String (pack (formatTime defaultTimeLocale "/Date(%s)/" t))
546+ toJSON t = String (pack (formatTime defaultTimeLocale "%FT%X%QZ" t))
529 {-# INLINE toJSON #-}
547 {-# INLINE toJSON #-}
531instance FromJSON UTCTime where
549instance FromJSON UTCTime where
532 parseJSON (String t) =
550 parseJSON (String t) =
533− case parseTime defaultTimeLocale "/Date(%s)/" (unpack t) of
551+ case parseTime defaultTimeLocale "%FT%X%QZ" (unpack t) of
534 Just d -> pure d
552 Just d -> pure d
535 _ -> empty
553 _ -> empty
536 parseJSON _ = empty
554 parseJSON _ = empty