JavaScriptSerializer is subtracting one day from date

Zaheer Ahmed picture Zaheer Ahmed · Feb 21, 2013 · Viewed 9k times · Source

I am using JavaScriptSerializer for serializing DateTime, but when I deserialize it show one day less from the date it get serialize:

Here is test:

  DateTime startDate=new DateTime(2012,1,20);//set the 20th of January
  JavaScriptSerializer  serializer=new JavaScriptSerializer();
  string serializeDate= serializer.Serialize(startDate);
  DateTime afterDeserialize= serializer.Deserialize<DateTime>(serializeDate);//I get 19th of Jan
  Assert.Equals(startDate, afterDeserialize);

firstly I thougt it because of javascript datetime format but as I know for javascript Month is zero index 0=January, but I am getting one day less than the original date.

Answer

Brad Christie picture Brad Christie · Feb 21, 2013

It's not losing a day arbitrarily, it's converting to a UTC date (or I should say using the date in a UTC date format) so when it's unserialized it you're no longer within your personal time zone. It's basically performing:

DateTime whateverDate = /* incoming date */;
long ticks = whateverDate.ToUniversalTime() // make UTC
  .Subtract(new DateTime(1970, 1, 1))       // subtract UNIX Epoch
  .TotalMilliseconds();                     // get milliseconds since then
// push in to the "\/Date(ticks)\/" format
String value = String.Format(@"\/Date({0})\/", ticks);

However, try the following:

// or you rely on it serializing, then bring it back to your own local time
// (apply the time zone).
afterDeserialize = afterDeserialize.ToLocalTime();

You'll now have the UTC time back to your local time (with time zone applied).


To Pass your test:

DateTime startDate              = new DateTime(2012,1,20);
JavaScriptSerializer serializer = new JavaScriptSerializer();
String serializeDate            = serializer.Serialize(startDate);
DateTime afterDeserialize       = serializer.Deserialize<DateTime>(serializeDate)
                                  .ToLocalTime(); // Note: this is added

Assert.Equals(startDate, afterDeserialize); // pass!