@@ -1,5 +1,5 @@
1−{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, IncoherentInstances,
2− OverlappingInstances, Rank2Types #-}
1+{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, GeneralizedNewtypeDeriving,
2+ IncoherentInstances, OverlappingInstances, Rank2Types #-}
33
44-- Module: Data.Aeson.Types
55-- Copyright: (c) 2011 MailRank, Inc.
@@ -19,6 +19,8 @@ module Data.Aeson.Types
1919 , Pair
2020 , Object
2121 , emptyObject
22+ -- * Convenience types
23+ , DotNetTime(..)
2224 -- * Type conversion
2325 , Parser
2426 , Result(..)
@@ -46,7 +48,7 @@ import Data.Ratio (Ratio)
4648import Data.Text (Text, pack, unpack)
4749import Data.Text.Encoding (decodeUtf8, encodeUtf8)
4850import Data.Time.Clock (UTCTime)
49−import Data.Time.Format (formatTime, parseTime)
51+import Data.Time.Format (FormatTime, formatTime, parseTime)
5052import Data.Typeable (Typeable)
5153import Data.Vector (Vector)
5254import Data.Word (Word, Word8, Word16, Word32, Word64)
@@ -522,15 +524,31 @@ instance FromJSON Value where
522524 parseJSON a = pure a
523525 {-# INLINE parseJSON #-}
524526
525−-- We happen to use the same JSON formatting for a UTCTime as .NET
526−-- does for a DateTime. How handy!
527+-- | A newtype wrapper for 'UTCTime' that uses the same non-standard
528+-- serialization format as Microsoft .NET.
529+newtype DotNetTime = DotNetTime UTCTime
530+ deriving (Eq, Ord, Read, Show, Typeable, FormatTime)
531+
532+instance ToJSON DotNetTime where
533+ toJSON (DotNetTime t) =
534+ String (pack (formatTime defaultTimeLocale "/Date(%s)/" t))
535+ {-# INLINE toJSON #-}
536+
537+instance FromJSON DotNetTime where
538+ parseJSON (String t) =
539+ case parseTime defaultTimeLocale "/Date(%s)/" (unpack t) of
540+ Just d -> pure (DotNetTime d)
541+ _ -> empty
542+ parseJSON _ = empty
543+ {-# INLINE parseJSON #-}
544+
527545instance ToJSON UTCTime where
528− toJSON t = String (pack (formatTime defaultTimeLocale "/Date(%s)/" t))
546+ toJSON t = String (pack (formatTime defaultTimeLocale "%FT%X%QZ" t))
529547 {-# INLINE toJSON #-}
530548
531549instance FromJSON UTCTime where
532550 parseJSON (String t) =
533− case parseTime defaultTimeLocale "/Date(%s)/" (unpack t) of
551+ case parseTime defaultTimeLocale "%FT%X%QZ" (unpack t) of
534552 Just d -> pure d
535553 _ -> empty
536554 parseJSON _ = empty