How to JSON stringify a javascript Date and preserve timezone

Solution 1:

Assuming you have some kind of object that contains a Date:

var o = { d : new Date() };

You can override the toJSON function of the Date prototype. Here I use moment.js to create a moment object from the date, then use moment's format function without parameters, which emits the ISO8601 extended format including the offset.

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

Now when you serialize the object, it will use the date format you asked for:

var json = JSON.stringify(o);  //  '{"d":"2015-06-28T13:51:13-07:00"}'

Of course, that will affect all Date objects. If you want to change the behavior of only the specific date object, you can override just that particular object's toJSON function, like this:

o.d.toJSON = function(){ return moment(this).format(); }

Solution 2:

I'd always be inclined to not mess with functions in the prototype of system objects like the date, you never know when that's going to bite you in some unexpected way later on in your code.

Instead, the JSON.stringify method accepts a "replacer" function (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The_replacer_parameter) which you can supply, allowing you to override the innards of how JSON.stringify performs its "stringification"; so you could do something like this;

var replacer = function(key, value) {

   if (this[key] instanceof Date) {
      return this[key].toUTCString();
   }
   
   return value;
}

console.log(JSON.stringify(new Date(), replacer));
console.log(JSON.stringify({ myProperty: new Date()}, replacer));
console.log(JSON.stringify({ myProperty: new Date(), notADate: "I'm really not", trueOrFalse: true}, replacer));