6

We have a .NET 4.7 MVC 5 web app, running under Windows, that allows users to select their time zone using the standard Windows display names like (UTC+00:00) Dublin, Edinburgh, Lisbon, London:

Windows time zone display names

We would like to provide the same list of time zone options through a new API built with .NET Core 2.0, which will run in a Linux docker container. Is this possible?

I have found Matt Johnson's excellent TimeZoneConverter package, which does a great job at converting between Windows's GMT Standard Time and IANA's Europe/London. However, I can't seem to get the Windows display name from anywhere.

Here's some example code to list some time zone information:

var timeZoneIds = TimeZoneConverter.TZConvert.KnownWindowsTimeZoneIds.ToList();

foreach (var timeZoneId in timeZoneIds.Take(4))
{
    if (TimeZoneConverter.TZConvert.TryGetTimeZoneInfo(timeZoneId, out var timeZoneInfo))
    {
        Console.WriteLine($"Windows Id:   {timeZoneId}");
        Console.WriteLine($".NET Id:      {timeZoneInfo.Id}");
        Console.WriteLine($"Display name: {timeZoneInfo.DisplayName}");
        Console.WriteLine("----");
    }
}

When run on my Windows development machine, it gives this output:

Windows Id:   AUS Central Standard Time
.NET Id:      AUS Central Standard Time
Display name: (UTC+09:30) Darwin
----
Windows Id:   AUS Eastern Standard Time
.NET Id:      AUS Eastern Standard Time
Display name: (UTC+10:00) Canberra, Melbourne, Sydney
----
Windows Id:   Afghanistan Standard Time
.NET Id:      Afghanistan Standard Time
Display name: (UTC+04:30) Kabul
----
Windows Id:   Alaskan Standard Time
.NET Id:      Alaskan Standard Time
Display name: (UTC-09:00) Alaska
----

When run inside a Linux docker container, we get this:

Windows Id:   AUS Central Standard Time
.NET Id:      Australia/Darwin
Display name: GMT+09:30
----
Windows Id:   AUS Eastern Standard Time
.NET Id:      Australia/Sydney
Display name: GMT+10:00
----
Windows Id:   Afghanistan Standard Time
.NET Id:      Asia/Kabul
Display name: GMT+04:30
----
Windows Id:   Alaskan Standard Time
.NET Id:      America/Anchorage
Display name: GMT-09:00
----

Is there any way to get (say) (UTC+10:00) Canberra, Melbourne, Sydney when running inside the Linux docker container?

Possible hacks or workarounds I've thought of so far:

  • Hard-code the list of Windows display names in the API source
  • Generate a "good enough" display name from the info that we do have, like (GMT+10:00) AUS Eastern Standard Time
  • See if Matt Johnson's TimeZoneNames package can used to generate a friendly list
Paul Stephenson
  • 67,682
  • 9
  • 49
  • 51
  • Does it have to be a single list of Windows-like display names? And is English your only localization requirement? – Matt Johnson-Pint Nov 14 '18 at 16:02
  • Also, have you considered an approach similar to this? http://timezonepickerdemo.azurewebsites.net – Matt Johnson-Pint Nov 14 '18 at 16:03
  • @MattJohnson it doesn't _have_ to be Windows display names, but that would provide consistency between our original app and UIs built using the new API. English is currently the only localization requirement. I have looked at your demo and it looks good, but might require too many changes in our UIs right now to move to the two-step country-and-timezone process! Thanks. – Paul Stephenson Nov 15 '18 at 11:10
  • 1
    I can probably add the Windows display names to TimeZoneNames. At least for English. Would that help? – Matt Johnson-Pint Nov 15 '18 at 15:17
  • Do you mean so that `var names = TZNames.GetNamesForTimeZone("AUS Eastern Standard Time", "en-GB");` would include (say) `names.WindowsDisplayName == "(UTC+10:00) Canberra, Melbourne, Sydney"`? Yes, I think that would be awesome! – Paul Stephenson Nov 15 '18 at 17:00
  • 1
    Added a feature request [here](https://github.com/mj1856/TimeZoneNames/issues/50). Let's keep this question open though, in case anyone has a better idea. :) – Matt Johnson-Pint Nov 15 '18 at 17:59

1 Answers1

7

This is now possible with TimeZoneNames version 4.0.0.

string languageCode = CultureInfo.CurrentCulture.IetfLanguageTag; // ex: "en-US"
var displayNames = TZNames.GetDisplayNames(languageCode);

The result is a dictionary where the key is the Windows ID of the time zone, and the value is the localized display name.

If you want to return IANA time zone names as keys instead, then pass true as an optional second parameter:

var displayNames = TZNames.GetDisplayNames(languageCode, true);
Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • Thank you for great tools! We're using both TZConvert and TZNames for linux-hosted .net core apps. Recently, I've found that while TZNames gives "(UTC+01:00) Casablanca" for "Morocco Standard Time" tz id, it's BaseUtcOffset is actually 00:00:00. Is this an issue with windows language packs or TZConvert/TZNames ? – Sergey Nikitin Jul 11 '19 at 08:17
  • Nope. That comes from the `TimeZoneInfo` object, and actually from the underlying TZDB data on the OS. Its actually normal. If you want me to go into details, please post a new question about that exact behavior. Thanks. – Matt Johnson-Pint Jul 11 '19 at 15:14
  • I get an error using this: "Could not find a language with code en-ZA". Seems others get the same error with other valid language codes. – Martin Lottering Jul 25 '23 at 19:47