Search code examples
c#.nettimezone.net-4.8timezone-offset

Why does the UTC offset in TimeZoneInfo.DisplayName not change for daylight saving time?


This question relates to the titles used within the Windows timezone database rather than actually converting times, from which there are many similarly-titled questions on SO - please flag if this is a duplicate and I'll remove it).

Last week I created a quick output test to understand the .Net Framework (4.8.1) TimeZoneInfo class and the property values within GetSystemTimeZones().

Over this last weekend many countries in Europe have switched to British Summer Time / Daylight Saving Time. Given this change, today the same iteration...

var zones = TimeZoneInfo.GetSystemTimeZones().OrderBy(z => z.Id);
foreach (TimeZoneInfo zone in zones)
{
    Console.WriteLine(zone.Id);
    Console.WriteLine(" " + zone.DisplayName);
    Console.WriteLine(" " + zone.DaylightName);
    Console.WriteLine();
}

... now produces slightly different results to last week:

GMT Standard Time
 (UTC+00:00) Dublin, Edinburgh, Lisbon, London
 GMT Summer Time

I note that in my output, TimeZoneInfo.DaylightName has switched accordingly to GMT Summer Time (I can't actually remember what it said last week but I think it was GMT Standard Time), but my confusion is why

(UTC+00:00) Dublin, Edinburgh, Lisbon, London

has not also become

(UTC+01:00) Dublin, Edinburgh, Lisbon, London

given the adjusted BST offset?

I'm trying to create a timezone selector for my user interface, but am concerned that titles used by TimeZoneInfo.DisplayName may be confusing.


Solution

  • Welcome to the confusing world of Windows time zones. There are a lot of things that don't make perfect sense. Several of them, including the offset in the display name, are mentioned in the timezone tag wiki in the section titled "Time Zone Databases", here on Stack Overflow. Much of that has to do with design choices that were made way back in the earliest days of Windows NT, and are still a part of Windows 11 today.

    To be clear, this isn't a .NET issue, but rather a Windows issue. One design has influenced the other. You're running .NET Framework on Windows, so you'll see Windows identifiers and display names when using TimeZoneInfo. However, if you were running .NET 6 or newer, on Linux or macOS, you'd instead see identifiers from IANA and display names derived from Unicode CLDR.

    Specifically regarding your question about the offset in the display name when running on Windows:

    • The entire DisplayName string, including the offset, is stored as a Windows resource string. It is localized by OS language, and updated via Windows Language Packs and Windows Updates.
    • The offset is the value that corresponds to TimeZoneInfo.BaseUtcOffset.
    • It does not change for DST, but might change when a Windows Update is applied, if a time zone's standard offset has changed.
    • It is not intended to represent the current offset, but rather what the user might think of as the current standard offset. For example, -08:00 for Pacific Time, regardless of whether PST or PDT is in effect.
    • The main reason offsets are included in the display name is for sorting them sequentially when displayed in a list. Without an offset, it might be difficult to locate a specific time zone.
      • If the offsets were to be dynamic, representing the current offset, then the values in the list (and the sort order) would potentially be different each time it was presented.
      • Picking a time zone is often associated with picking a date/time for an event. There's no guarantee that the offset in the list is the correct one on the event date, regardless of whether the offsets are static or dynamically associated with the current time. They'd instead have to be associated with the date/time of the event, which would require a new API to generate the list based on a particular date/time.

    A few other points:

    • The offset in England during BST is +01:00, not +00:01
    • Along with DisplayName, the StandardName and DaylightName properties are also localized per language - using the OS language on Windows. (The Id property is not localized.)
    • On Windows, the actual values of the Id, StandardName, and DaylightName properties are often made-up and sometimes confusing. Some of them are complete rubbish, IMHO. I would avoid showing them to a user, if you can at all help it.
    • You might find my TimeZoneNames library useful to resolve some of your concerns, but you will still need to think through exactly what behavior you want your application to have.