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

json.net

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.

Best Answer

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)\/"}