Commits

Bryan O'Sullivan committed dce31dc

Parse and serialize .NET System.DateTime values correctly.

The number in parentheses in the default JSON serialization of a a .NET
DateTime is milliseconds since the Unix epoch, whereas I had been treating
it as seconds.

Comments (0)

Files changed (1)

Data/Aeson/Types.hs

 {-# LANGUAGE DeriveDataTypeable, FlexibleInstances, GeneralizedNewtypeDeriving,
-    IncoherentInstances, OverlappingInstances, Rank2Types #-}
+    IncoherentInstances, OverlappingInstances, OverloadedStrings, Rank2Types #-}
 
 -- |
 -- Module:      Data.Aeson.Types
     {-# INLINE parseJSON #-}
 
 -- | A newtype wrapper for 'UTCTime' that uses the same non-standard
--- serialization format as Microsoft .NET.
+-- serialization format as Microsoft .NET, whose @System.DateTime@
+-- type is by default serialized to JSON as in the following example:
+--
+-- > /Date(1302547608878)/
+--
+-- The number represents milliseconds since the Unix epoch.
 newtype DotNetTime = DotNetTime {
       fromDotNetTime :: UTCTime
     } deriving (Eq, Ord, Read, Show, Typeable, FormatTime)
 
 instance ToJSON DotNetTime where
     toJSON (DotNetTime t) =
-        String (pack (formatTime defaultTimeLocale "/Date(%s)/" t))
+        String (pack (secs ++ msecs ++ ")/"))
+      where secs  = formatTime defaultTimeLocale "/Date(%s" t
+            msecs = take 3 $ formatTime defaultTimeLocale "%q" t
     {-# INLINE toJSON #-}
 
 instance FromJSON DotNetTime where
     parseJSON (String t) =
-        case parseTime defaultTimeLocale "/Date(%s)/" (unpack t) of
+        case parseTime defaultTimeLocale "/Date(%s%Q)/" (unpack t') of
           Just d -> pure (DotNetTime d)
           _      -> fail "could not parse .NET time"
+      where (s,m) = T.splitAt (T.length t - 5) t
+            t'    = T.concat [s,".",m]
     parseJSON v   = typeMismatch "DotNetTime" v
     {-# INLINE parseJSON #-}
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.