Search code examples
.netdatetimetimezoneutc

How does .Net TimeZoneInfo.GetUtcOffset work?


I'm reading the document of TimeZoneInfo.GetUtcOffset at https://learn.microsoft.com/en-us/dotnet/api/system.timezoneinfo.getutcoffset?view=netframework-4.8 and I'm a little bit confused. The document states that this method

Calculates the offset or difference between the time in this time zone and Coordinated Universal Time (UTC) for a particular date and time.

But as I understand, for a specific time, people in different timezones use different numbers to denote them. If I'm in Japan using the timezone UTC+9 and Michael is in somewhere using UTC. I talk to him on Skype and we have different local time. My local time and Michael's local time always has the exact same difference. If my local time is 10:00 am, his is 1:00 am. If mine is 10:01 am, his is 1:01 am. The difference is the same and it can be determined by only my timezone and his timezone and the time itself is not relevant.

So TimeZoneInfo.GetUtcOffset is calculating the difference between the time in this time zone and Coordinated Universal Time (UTC) for a particular date and time. It looks like it's the same as my aforementioned example. My local time is 10:00 am, what's the difference between my local time and Michael's? Here the time should not be needed. Why the method takes a DateTime or DateTimeOffset parameter?


Solution

  • A few things:

    • A time zone is much more than just a numeric offset. Many time zones change their offsets regularly, such as when Pacific Time in the United States transitions between UTC-8 (PST) and UTC-7 (PDT) for daylight saving time. Additionally, several time zones have had changes to their standard time, such as when Venezuela switched from UTC-4:30 to UTC-4 in 2016. For more on this, read "Time Zone != Offset" in the timezone tag wiki.

    • A TimeZoneInfo object represents the complete set of states of a time zone, including all offsets that it uses or may have used. (Since at least 2010 on Windows and since at least 1970 on other platforms.)

      • Side note: Try not to read too much into the names of the identifiers used in Windows. There are lots of confusing naming conventions, such as "Pacific Standard Time" being the ID that covers both PST and PDT. More examples are listed in the timezone tag wiki.
    • Thus, to know which offset one wants returned from GetUtcOffset, one has to provide a point in time, preferably with a DateTimeOffset object since it represents a distinct point in time.

      • If you provide a DateTime object instead, then its Kind property matters. If it is DateTimeKind.Local or DateTimeKind.Utc then the point in time you are referencing is distinct. However, if it's DateTimeKind.Unspecified, then there's a potential for the value to be ambiguous or invalid. For example, 2019-03-10T02:30:00 does not exist in US Pacific Time, because the clocks advance from 1:59:59 to 03:00:00 for the start of DST. Conversely, 2019-11-03T01:30:00 exists twice in Pacific Time, because the clocks move back from 01:59:59 to 01:00:00 for the end of DST. Note that the methods of the TimeZoneInfo object will always infer standard time in such cases, which may or may not be ideal for your scenarios. In many cases, the daylight time is preferred.
    • In your example, note that it wouldn't be usual for Michael to be "somewhere using UTC". Local time zones, for a given point in time, are always expressed using offsets from UTC. Sometimes that offset is zero. For example, London uses GMT (UTC+0) during standard time and BST (UTC+1) during daylight saving time (aka "summer time"). If Michael was in London, then it would be important to know if BST was in effect or not.

      • Note that UTC isn't technically a "time zone", but rather a standard for timekeeping. It appears in the list of available time zones because sometimes one needs to have a computer just track time in UTC. This is the best practice for servers, but is not common for local computers or devices.

      • Even in Japan, UTC+9 has not always been the offset. Japan previously used UTC+10, last in 1951. This detail isn't in the Windows time zone data due to its age, but does exist in the IANA time zone data used natively on other platforms, and available in .NET via the TZDB provider in Noda Time.