Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent Json.NET 4.5 from appending timezone offset when using MicrosoftDateFormat

Tags:

Short of a custom DateTimeConverterBase implementation, is there some way to keep Json.NET 4.5+, when set to use DateFormatHandling.MicrosoftDateFormat, from appending a timezone offset for any non-UTC DateTime it is given?

"\/Date(1333645844276-0600)\/"

Details

I am switching an API project from using the built-in .NET JavaScriptSerializer to using Json.NET to generate JSON. In Json.NET, for a UTC DateTime, the default datetime serialization was similar to the .NET version:

"\/Date(1333645844276)\/"

For non-UTC, unlike JavaScriptSerializer, Json.NET appends a timezone offset to the results (-6 for my area, this time of year):

"\/Date(1333645844276-0600)\/"

Here is the code I am using to switch Json.NET 4.5+ back to the \/Date(...)\/ format (called MicrosoftDateFormat):

JsonSerializerSettings customJsonSettings = new JsonSerializerSettings() {
    DateFormatHandling = DateFormatHandling.MicrosoftDateFormat
};
string result = JsonConvert.SerializeObject(DateTime.Now, customJsonSettings);

The solution seemed like it would be as simple as telling Json.NET to use a different DateTimeZoneHandling setting. I have tried every setting for DateTimeZoneHandling (Local, Utc, Unspecified, and RoundtripKind) and they all maintain the "-0600" in the output. In fact, they all produce identical results for a non-UTC DateTime.

JsonSerializerSettings customJsonSettings = new JsonSerializerSettings() {
    DateFormatHandling = DateFormatHandling.MicrosoftDateFormat,
    DateTimeZoneHandling = DateTimeZoneHandling.Utc
};
string result = JsonConvert.SerializeObject(DateTime.Now, customJsonSettings);
"\/Date(1333647855743-0600)\/"

Caveat

Ideally, I would have all my times in UTC already. I certainly plan to do so with the next version of this API. Since this is a live API, it is not worth risking an output change until a new version is released. It doesn't appear to be an issue for most JSON parsing systems, but I cannot risk the change since the JSON standard doesn't officially say anything about date serialization.

like image 381
patridge Avatar asked Apr 05 '12 18:04

patridge


1 Answers

It seems to work just fine for me, see below. My JSON.NET assembly says it's version "4.5.0.0".

JsonSerializerSettings customJsonSettings = new JsonSerializerSettings()
{
    DateFormatHandling = DateFormatHandling.MicrosoftDateFormat,
    DateTimeZoneHandling = DateTimeZoneHandling.Utc
};
string result = JsonConvert.SerializeObject(DateTime.Now, customJsonSettings);
Console.WriteLine(result); // "\/Date(1344249339881)\/"

Perhaps it was a bug that has been fixed?

Explicitly creating a date:

var x = new { thedate = new DateTime(2009, 2, 15, 0, 0, 0, DateTimeKind.Local) };

Console.WriteLine(JsonConvert.SerializeObject(x,
    new JsonSerializerSettings() {
        DateFormatHandling = DateFormatHandling.MicrosoftDateFormat
    }));
// {"thedate":"\/Date(1234652400000+0100)\/"}

Console.WriteLine(JsonConvert.SerializeObject(x,
    new JsonSerializerSettings() {
        DateFormatHandling = DateFormatHandling.MicrosoftDateFormat,
        DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc
    }));
// {"thedate":"\/Date(1234652400000)\/"}

Console.WriteLine(JsonConvert.SerializeObject(x,
    new JsonSerializerSettings() {
        DateFormatHandling = DateFormatHandling.MicrosoftDateFormat,
        DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Local
    }));
// {"thedate":"\/Date(1234652400000+0100)\/"}
like image 148
johv Avatar answered Sep 21 '22 05:09

johv