Search code examples
c#datetime.net-coretimezonejsonserializer

How JSON deserialize datetime and convert from UTC to a specified time zone?


I want to create a custom json serializer that will convert objects with dateTime to and from UTC and back to a specified time zone. (Not local)

Example which converts to UTC is:

MyObject stuff = new MyObject();
stuff.Date = DateTime.Now;

string asdd = JsonConvert.SerializeObject(stuff,
            new JsonSerializerSettings()
            {
                DateTimeZoneHandling = DateTimeZoneHandling.Utc
            });

How do I convert from UTC back to a specific timezone via JsonSerializerSettings or a custom serializer?

Note: I'm working in .NET Core 2.1.


Solution

  • Time zone conversion should not be handled at time of serialization or deserialization. Those are separate concerns.

    Instead:

    Leave DateTimeZoneHandling at its default of RoundtripKind. (Don't set it to Utc.) This has the behavior of:

    • If you are deserializing to a DateTime, and passing no offset in your data, then DateTimeKind.Unspecified will be set.
    • If you are deserializing to a DateTime, and passing a trailing Z in your data, then DateTimeKind.Utc will be set.
    • If you are deserializing to a DateTime, and passing an offset in your data, then `DateTimeKind.Local will be set, and the value will be converted to the local time zone (generally one should avoid this).
    • If you are deserializing to a DateTimeOffset, then the offset will be persisted and the value will not change (this is the better approach if passing offsets).

    Once you have a DateTime or DateTimeOffset value, then use TimeZoneInfo.ConvertTime and similar methods to change time zones if necessary. This part should be in your application code, as it tends to be specific to the logic of a particular API.

    Generally speaking, it's an antipattern (SRP violation) to try to treat all incoming or outgoing date/time data to be in the same time zone, whether via serialization or some other mechanism.