Ian Grainger
Ian Grainger

Reputation: 5516

JsonConvert not converting UTC -> Local time in PopulateObject

I have a date coming from javascript via toJSON, so it's stored as a UTC time, but I'd like to store it in the database as local time (we've never stored UTC times in the past, so I need to continue the trend here).

However, setting DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Local (with version 6.0.0.0 of Newtonsoft.Json) when running PopulateObject doesn't do anything, it's still left as a UTC date with the original time.

My question is: why is it not running dt.ToLocalTime() which fixes the problem (and is my current workaround) - or: how do I get the converter to do that, if not from the DateTimeZoneHandling.Local setting?

Upvotes: 3

Views: 1677

Answers (1)

Matt Johnson-Pint
Matt Johnson-Pint

Reputation: 241555

Storing a DateTime into a database as local time is generally not a great idea, because:

  • If your local time zone has daylight saving time rules, then you could potentially be losing data. During the fall-back transition, there's a one-hour period where a local time could represent two possible moments. Using UTC avoids this issue.

  • It binds your data to a particular location. If you ever need to migrate your server to another location (or to the cloud), your past data will be inaccurate.

If you must store your data in local time, consider storing it as a DateTimeOffset. By recording the offset, you can accurately distinguish the unique point in time it represents, if the local time zone changes. This adequately counters both of the points above.

See also: DateTime vs DateTimeOffset.

As to your question about JSON.Net and the DateTimeZoneHandling.Local option, this simple example shows that it appears to be working as designed. I can't reproduce your claim.

public class Foo
{
    public DateTime DateTime { get; set; }
}

...

var json = "{\"DateTime\":\"2014-01-01T00:00:00.000Z\"}";

var settings = new JsonSerializerSettings
                    {
                        DateTimeZoneHandling = DateTimeZoneHandling.Local
                    };

var foo = JsonConvert.DeserializeObject<Foo>(json, settings);

Debug.WriteLine("{0} ({1})", foo.DateTime, foo.DateTime.Kind);

Output:

12/31/2013 16:00:00 (Local)

My local time zone is US Pacific Time, which was 8 hours behind UTC on the date provided, which is reflected in the results.

Upvotes: 5

Related Questions