11
{ id: 1533,
  story_type_id: 1,
  content_id: 470,
  created_at: Sun, 05 Feb 2012 07:02:43 GMT,
  updated_at: Sun, 05 Feb 2012 07:02:43 GMT,
  type_name: 'post' }

I have a JSON object with the "datetime" field like above. It's perfect. But when I stringify it (I want to store it in cache), I get this format:

"created_at":"2012-02-05T07:02:43.000Z"

This causes problems, because when I want to JSON.parse this, suddenly it's no longer datetime format and it's incompatible with my other format.

What can I do to solve this problem? I have 'created_at' littered everywhere throughout my application. I don't want to manually change each one.

TIMEX
  • 259,804
  • 351
  • 777
  • 1,080
  • Presumably you're serialising these dates to store them in localStorage. In that case, you can avoid aggro like this and similar by using a wrapper library like rhaboo. – Adrian May Apr 21 '15 at 05:11

4 Answers4

17

It is actually possible to modify how a Date object will be serialized into JSON. Combined with the reviver function, a bi-directional solution can be created which will automatically work on serialization and can easily be used on deserialization.

First modify the serialization like this:

Date.prototype.toJSON = function() { return "{timestamp}+" . this.getTime() }

This will change the representation of a Date object into a UNIX timestamp with a prefix as a marker:

> json = JSON.stringify({test:new Date()});
"{"test":"{timestamp}1380164268633"}"

Then you can create a reviver function which will automatically filter out these values:

function json_deserialize_helper(key,value) {
  if ( typeof value === 'string' ) {
    var regexp;
    regexp = /^{timestamp}(\d*)$/.exec(value);
    if ( regexp ) {
      return new Date(+regexp[1]);
    }
  }
  return value;
}

(Credit: This code was basically copied from this answer in a related question: https://stackoverflow.com/a/14509447/2572897)

Now with this setup, deserialization of our result from before will result in a Date object again:

> JSON.parse(json, json_deserialize_helper);
Object {test: Thu Sep 26 2013 04:57:48 GMT+0200 (CEST)}

Or you can choose not to modify the serialization but instead use the regexp to catch the standard serialization format:

function json_deserialize_helper(key,value) {
  if ( typeof value === 'string' ) {
    var regexp;
    regexp = /^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\d\d\dZ$/.exec(value);
    if ( regexp ) {
      return new Date(value);
    }
  }
  return value;
}

Example:

> json = JSON.stringify({test:new Date()})
"{"test":"2013-09-26T03:05:26.563Z"}"
> JSON.parse(json, json_deserialize_helper)
Object {test: Thu Sep 26 2013 05:05:26 GMT+0200 (CEST)}
Community
  • 1
  • 1
Juliane Holzt
  • 2,135
  • 15
  • 14
  • this is really depend on the field name. What if there is a lot of fields that must be in Date instance? Handle all fields in the reviever function? Or is there any regex expression that can detect date format? – alramdein Sep 23 '21 at 06:30
  • It does not depend on the field name. Check the code again. There is a regexp. You might have confused this with another answer which actually depends on a field name. – Juliane Holzt Sep 30 '21 at 17:20
15

There is not special way to serialize Date objects in JSON. That's why you get the standardized string representation. You need to convert them back to Date objects by passing them to the Date constructor.

item['created_at'] = new Date(item['created_at']);

Update: With the reviver function (see comments), you can get the Date objects back.

var item = JSON.parse(row, function (key, value) {
  if (key === 'created_at') {
    return new Date(value);
  } else {
    return value;
  }
});
J. K.
  • 8,268
  • 1
  • 36
  • 35
  • So there's nothing I can do about it? – TIMEX Feb 08 '12 at 13:47
  • No, I don't think so. You would have to store it some other way. – J. K. Feb 08 '12 at 13:49
  • The `Date` object is native to JavaScript, but JSON is a serialization mechanism used to transport data between platforms. If it allowed serialization of native objects and functions, systems which transmit JSON from JS to, say, PHP would break. You may want to look into the JSON `reviver` methodologies. – JAAulde Feb 08 '12 at 13:51
  • 1
    @JanKuča what if I store it like that, but during retrieval, I iterate through each key and check if it's a date. If so, apply new Date() to it? http://stackoverflow.com/questions/9194576/how-do-i-determine-if-a-string-is-date-format – TIMEX Feb 08 '12 at 13:54
  • 1
    @JanKuča , what if I don't know the "created_at" part? I have so many like that...I don't know the key name. I'll have to use regex to check if it's a date or not. – TIMEX Feb 08 '12 at 14:03
  • Yes, you would have to check the value agains a `RegExp` along the lines of `/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+Z$/` – J. K. Feb 08 '12 at 14:05
  • can I try{ result[k] = new Date(result[k]) }catch(){}; (blank catch statement) – TIMEX Feb 08 '12 at 14:11
  • That does not work. No error is thrown. Try `var date = new Date(value); value = isNaN(date.getTime()) ? date : value;` – J. K. Feb 08 '12 at 14:15
2
var date = new Date();
console.log(date);//Mon Jun 11 2018 10:14:33 GMT+0430 (Iran Daylight Time)
var json = JSON.stringify(date);
console.log(json);//"2018-06-11T05:44:33.590Z"
var dateStr = JSON.parse(json);  
console.log(dateStr);//2018-06-11T05:44:33.590Z
var date = new Date(dateStr);
console.log(date);//Mon Jun 11 2018 10:14:33 GMT+0430 (Iran Daylight Time)

https://weblog.west-wind.com/posts/2014/Jan/06/JavaScript-JSON-Date-Parsing-and-real-Dates

Majid joghataey
  • 1,488
  • 2
  • 17
  • 28
1

Date.prototype.toJSON = function() { return moment(this).format('L'); }

You can read more about moment documentation and tailor type of date you want to return.

Navid Golforoushan
  • 728
  • 1
  • 9
  • 16