Vincent Costel

Json.NET unexpected defaults for parsing date

I stumbled upon weird date parsing issues with Json.NET so I figured I should document my findings here for future me, when I will scratch my head over the exact same problem in a few months/years.

Here is a simple JSON document with a single property date set to the current time in France. JSON does't have a date format so I used an ISO8601 string:

  {
"date": "2017-12-02T21:21:00+01:00"
}

Let's try to read back that date:

  var obj = JObject.Parse(json);
var date = obj.Value<string>("date");

I would expect the value of date to be "2017-12-02T21:21:00+01:00". Instead, the value is 12/02/2017 15:21:00, which is the date converted to my current time zone, and I'm not sure what the format is.

Why? Because, by default, if the parser recognizes an ISO8601 date string, it will automatically convert it to a DateTime object, therefore losing the time offset value. By default, it also converts the date to local time.
Then, doing obj.Value<string>("date") will just output the string representation of the parsed date.

This was really unexpected for me. I assumed that since there is no date format in JSON, it would just read the date property as a string. Another possibility would be to use DateTimeOffset when parsing the date in order to keep the time offset information. In my opinion, the default behavior is the least intuitive, but it probably is for backward compatibility reasons.

In order to get the original date, the default serializer settings must be changed. Here's one way to do it:

  JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
DateParseHandling = DateParseHandling.DateTimeOffset,
};

var obj = JObject.Parse(json);
var date = obj.Value<DateTimeOffset>("date");

Now the ISO8601 string is converted to a DateTimeOffset object, keeping the original time offset value.

I found this solution in a GitHub issue where the same problem was reported.