Deserializing Client-Side AJAX JSON Dates
Given the following JSON Date representation:
"\/Date(1221644506800-0700)\/"
How do you deserialize this into it's JavaScript Date-type form?
I've tried using MS AJAX JavaScrioptSerializer as shown below:
Sys.Serialization.JavaScriptSerializer.deserialize("\/Date(1221644506800-0700)\/")
However, all I get back is the literal string date.
7 answers given for "Deserializing Client-Side AJAX JSON Dates"
Accepted Solution
Provided you know the string is definitely a date I prefer to do this :
new Date(parseInt(value.replace("/Date(", "").replace(")/",""), 10))
Bertrand LeRoy, who worked on ASP.NET Atlas/AJAX, described the design of the JavaScriptSerializer DateTime output and revealed the origin of the mysterious leading and trailing forward slashes. He made this recommendation:
run a simple search for "\/Date((\d+))\/" and replace with "new Date($1)" before the eval (but after validation)
I implemented that as:
var serializedDateTime = "\/Date(1271389496563)\/";
document.writeln("Serialized: " + serializedDateTime + "<br />");
var toDateRe = new RegExp("^/Date\\((\\d+)\\)/$");
function toDate(s) {
if (!s) {
return null;
}
var constructor = s.replace(toDateRe, "new Date($1)");
if (constructor == s) {
throw 'Invalid serialized DateTime value: "' + s + '"';
}
return eval(constructor);
}
document.writeln("Deserialized: " + toDate(serializedDateTime) + "<br />");
This is very close to the many of the other answers:
- Use an anchored RegEx as Sjoerd Visscher did -- don't forget the ^ and $.
- Avoid string.replace, and the 'g' or 'i' options on your RegEx. "/Date(1271389496563)//Date(1271389496563)/" shouldn't work at all.
A JSON value is a string, number, object, array, true, false or null. So this is just a string. There is no official way to represent dates in JSON. This syntax is from the asp.net ajax implementation. Others use the ISO 8601 format.
You can parse it like this:
var s = "\/Date(1221644506800-0700)\/";
var m = s.match(/^\/Date\((\d+)([-+]\d\d)(\d\d)\)\/$/);
var date = null;
if (m)
date = new Date(1*m[1] + 3600000*m[2] + 60000*m[3]);
The regular expression used in the ASP.net AJAX deserialize method looks for a string that looks like "/Date(1234)/" (The string itself actually needs to contain the quotes and slashes). To get such a string, you will need to escape the quote and back slash characters, so the javascript code to create the string looks like "\"\/Date(1234)\/\"".
This will work.
Sys.Serialization.JavaScriptSerializer.deserialize("\"\\/Date(1221644506800)\\/\"")
It's kind of weird, but I found I had to serialize a date, then serialize the string returned from that, then deserialize on the client side once.
Something like this.
Script.Serialization.JavaScriptSerializer jss = new Script.Serialization.JavaScriptSerializer();
string script = string.Format("alert(Sys.Serialization.JavaScriptSerializer.deserialize({0}));", jss.Serialize(jss.Serialize(DateTime.Now)));
Page.ClientScript.RegisterStartupScript(this.GetType(), "ClientScript", script, true);
For those who don't want to use Microsoft Ajax, simply add a prototype function to the string class.
E.g.
String.prototype.dateFromJSON = function () {
return eval(this.replace(/\/Date\((\d+)\)\//gi, "new Date($1)"));
};
Don't want to use eval? Try something simple like
var date = new Date(parseInt(jsonDate.substr(6)));
As a side note, I used to think Microsoft was misleading by using this format. However, the JSON specification is not very clear when it comes to defining a way to describe dates in JSON.
Actually, momentjs supports this kind of format, you might do something like:
var momentValue = moment(value);
momentValue.toDate();
This returns the value in a javascript date format
The big number is the standard JS time
new Date(1221644506800)
Wed Sep 17 2008 19:41:46 GMT+1000 (EST)