Time Zones and DateTimeOffset
Learn why using DateTime can lead to bugs across time zones, how to safely store exact moments with DateTimeOffset, and how to convert times between zones using TimeZoneInfo.
We'll cover the following...
The DateTime struct is useful, but it lacks built-in time zone awareness. It relies on a Kind property that only indicates if the time is Local, Utc, or Unspecified. Serialization formats like JSON and many database providers often strip or ignore this Kind property. If a server reads 2024-05-10 14:00:00 from a database, it cannot definitively know if that represents 2:00 PM in Tokyo, London, or New York.
Additionally, relying on local DateTime values makes our code highly vulnerable to Daylight Saving Time (DST) bugs. If we add 24 hours to a local DateTime on the day the clocks spring forward, the resulting time will be incorrect because that specific calendar day only has 23 hours.
The DateTimeOffset struct
To solve these ambiguities and arithmetic problems, modern C# relies on the DateTimeOffset struct.
A DateTimeOffset stores the exact date and time, just like DateTime. However, it also natively stores a TimeSpan representing the exact offset from Coordinated Universal Time (UTC). Because the offset is stored alongside the date and time, a DateTimeOffset always represents a single, unambiguous point in time.