The “right” JSON date format

The “right” JSON date format

I’ve seen so many different standards for the JSON date format:
“\”\\/Date(1335205592410)\\/\”” .NET JavaScriptSerializer
“\”\\/Date(1335205592410-0500)\\/\”” .NET DataContractJsonSerializer
“2012-04-23T18:25:43.511Z” JavaScript built-in JSON object
“2012-04-21T18:25:43-05:00” ISO 8601

Which one is the right one? Or best? Is there any sort of standard on this?

Solutions/Answers:

Solution 1:

JSON itself does not specify how dates should be represented, but JavaScript does.

You should use the format emitted by Date‘s toJSON method:

2012-04-23T18:25:43.511Z

Here’s why:

  1. It’s human readable but also succinct

  2. It sorts correctly

  3. It includes fractional seconds, which can help re-establish chronology

  4. It conforms to ISO 8601

  5. ISO 8601 has been well-established internationally for more than a decade

  6. ISO 8601 is endorsed by W3C, RFC3339, and XKCD

That being said, every date library ever written can understand “milliseconds since 1970”. So for easy portability, ThiefMaster is right.

Solution 2:

JSON does not know anything about dates. What .NET does is a non-standard hack/extension.

I would use a format that can be easily converted to a Date object in JavaScript, i.e. one that can be passed to new Date(...). The easiest and probably most portable format is the timestamp containing milliseconds since 1970.

Solution 3:

There is no right format; The JSON specification does not specify a format for exchanging dates which is why there are so many different ways to do it.

The best format is arguably a date represented in ISO 8601 format (see Wikipedia); it is a well known and widely used format and can be handled across many different languages, making it very well suited for interoperability. If you have control over the generated json, for example, you provide data to other systems in json format, choosing 8601 as the date interchange format is a good choice.

If you do not have control over the generated json, for example, you are the consumer of json from several different existing systems, the best way of handling this is to have a date parsing utility function to handle the different formats expected.

Solution 4:

From RFC 7493 (The I-JSON Message Format ):

I-JSON stands for either Internet JSON or Interoperable JSON, depending on who you ask.

Protocols often contain data items that are designed to contain
timestamps or time durations. It is RECOMMENDED that all such data
items be expressed as string values in ISO 8601 format, as specified
in RFC 3339, with the additional restrictions that uppercase rather
than lowercase letters be used, that the timezone be included not
defaulted, and that optional trailing seconds be included even when
their value is “00”. It is also RECOMMENDED that all data items
containing time durations conform to the “duration” production in
Appendix A of RFC 3339, with the same additional restrictions.

Solution 5:

Just for reference I’ve seen this format used:

Date.UTC(2017,2,22)

It works with JSONP which is supported by the $.getJSON() function. Not sure I would go so far as to recommend this approach… just throwing it out there as a possibility because people are doing it this way.

FWIW: Never use seconds since epoch in a communication protocol, nor milliseconds since epoch, because these are fraught with danger thanks to the randomized implementation of leap seconds (you have no idea whether sender and receiver both properly implement UTC leap seconds).

Kind of a pet hate, but many people believe that UTC is just the new name for GMT — wrong! If your system does not implement leap seconds then you are using GMT (often called UTC despite being incorrect). If you do fully implement leap seconds you really are using UTC. Future leap seconds cannot be known; they get published by the IERS as necessary and require constant updates. If you are running a system that attempts to implement leap seconds but contains and out-of-date reference table (more common than you might think) then you have neither GMT, nor UTC, you have a wonky system pretending to be UTC.

These date counters are only compatible when expressed in a broken down format (y, m, d, etc). They are NEVER compatible in an epoch format. Keep that in mind.

Solution 6:

JSON itself has no date format, it does not care how anyone stores dates. However, since this question is tagged with javascript, I assume you want to know how to store javascript dates in JSON. You can just pass in a date to the JSON.stringify method, and it will use Date.prototype.toJSON by default, which in turns uses Date.prototype.toISOString (MDN on Date.toJSON):

const json = JSON.stringify(new Date());
const parsed = JSON.parse(json); //2015-10-26T07:46:36.611Z
const date = new Date(parsed); // Back to date object

I also found it useful to use the reviver parameter of JSON.parse (MDN on JSON.parse) to automatically convert ISO strings back to javascript dates whenever I read JSON strings.

const isoDatePattern = new RegExp(/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/);

const obj = {
 a: 'foo',
 b: new Date(1500000000000) // Fri Jul 14 2017, etc...
}
const json = JSON.stringify(obj);

// Convert back, use reviver function:
const parsed = JSON.parse(json, (key, value) => {
    if (typeof value === 'string' &&  value.match(isoDatePattern)){
        return new Date(value); // isostring, so cast to js date
    }
    return value; // leave any other value as-is
});
console.log(parsed.b); // // Fri Jul 14 2017, etc...