parseJSON for the variations on ISO-8601 dates as listed in ECMA-262. #64

merged 2 commits into from Nov 20, 2012

5 participants


A follow-up to #58, this handles all the permutations of dates as specified in ECMA-262, for the ZonedTime type.


The comment in bos#1 (comment) w.r.t. to millisecond precision applies here as well (%Q has much more decimals than supported by ECMA-262 -- actually the ECMA-262 spec seems to require exactly 3 digits even in case of trailing zeros)

You're right, this would produce an invalid JSON date.

I can't think of a better solution than using take. Ideally the time formatter would take a numeric offset so we could say %3Q, but no such luck yet.


this also accepts timestamps without any utc-offset which represent a type-error, since a ZonedTime represents a time with an associated utc-offset...

'The value of an absent time zone offset is "Z"', according to ECMA-262. I took this to mean that this would be fine as a ZonedTime, with an offset of +00:00.


You're right, that's what the spec says... but it's rather unfortunate the spec is type-unsafe in this regard, as it makes it impossible to distinguish a LocalTime from a ZonedTime defaulting to UTC-offset this way;

I have a few web-service backends written in Python and Haskell with several JSON-RPC services (for which I have written ToJSON/FromJSON instances similar to yours), for which I require the clients to be specific whether they mean local-time 1995-02-05T12:32 or absolute time 1995-02-05T12:32Z... and unfortunately many developers don't think much about timezones, so this has caught many misunderstandings early on, by forcing them to be explicit...

I'm a bit undecided here, whether it's better to strictly follow the spec, and accept a weaker JSON "typesystem" w.r.t. to the LocalTime vs. ZonedTime serialization (converting a LocalTime to JSON, and parsing that back as a ZonedTime would silently convert it to UTC time, which is one of the bugs I've fought against in the past) vs. ignoring that "absent timezone defaults to Z" passage...


Updated to fix the toJSON bug that @hvr found.


btw, padding with 0s could be easily accomplished by testing for non-zero milliseconds (which would safe us from calling formatTime "%Q" in the first place for whole-seconds) and then just using take 4 $ formatTime ... "%Q" t ++ "000"


I haven't looked at the patch in detail yet but is the

deriving instance Eq ZonedTime

necessary? The disadvantage of this instance is that users will automatically import this instance when they import Data.Aeson which may then conflict with their possibly custom defined instance.

Can we make do with a custom defined function like:

eq :: ZonedTime -> ZonedTime -> Bool
eq (ZonedTime lt1 tz1) (ZonedTime lt2 tz2) = lt1 == lt2 && tz1 == tz2

jfyi, I just noticed, that the following quote from the latest ECMA-262 draft wasn't part of the ECMA-262 5ed version, but was added in the ECMA-262 5.1ed:

If the MM or DD fields are absent “01” is used as the value. If the mm or ss
fields are absent “00” is used as the value and the value of an absent sss file is “000”. The value of an
absent time zone offset is “Z”.

Thus, for reasons I can't comprehend yet, ECMA-262 5.1ed lost the ability to represent "naive" (date)times... :-(


on the other hand, see, and indeed, in the last ECMA-262 6ed draft (July 25, 2011) that last sentence was changed again to read:

If the time zone offset is absent, the date-time is in interpreted as a local time.

So the ECMA-262 5.1ed was just a minor misstep it seems...

@bmillwood bmillwood referenced this pull request Aug 26, 2012

Instances for ZonedTime #86


Having accidentally independently invented this in #86, I'm interested in helping it along. What's the status on it?

@bos bos merged commit 4529c6a into bos:master Nov 20, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment