Coder Perfect

What is the best way to convert between Windows and IANA time zones?


There are two types of time zones, as defined in the timezone tag wiki.

Many Internet-based APIs use IANA time zones, however for a variety of reasons, this may need to be converted to a Windows time zone id or vice versa.

Is there a d in.Net?

Asked by Matt Johnson-Pint

Solution #1

Both types of time zones are supported starting with.NET 6, on any platform that has both time zone data and ICU installed, which is most Windows, Linux, and MacOS installations. Take a look at Tobias’ response.

The windowsZones.xml file, published as part of the Unicode CLDR project, is the primary source of data for converting between Windows and IANA time zone designations. The most recent development version is available here.

CLDR, on the other hand, is only released twice a year. This, combined with the regular frequency of Windows updates and the sporadic changes of the IANA time zone database, makes using CLDR data directly difficult. Keep in mind that time zone changes are implemented at the whim of many governments throughout the world, and not all changes are announced with enough time to make it into these release cycles before their respective effective dates.

There are a few other edge circumstances that must be addressed that are not covered by the CLDR, and new ones arise on a regular basis. As a result, I’ve encased the solution’s complexity in the TimeZoneConverter micro-library, which you can acquire from Nuget.

It’s easy to use this library. Here are some conversion examples:

string tz = TZConvert.IanaToWindows("America/New_York");
// Result:  "Eastern Standard Time"

string tz = TZConvert.WindowsToIana("Eastern Standard Time");
// result:  "America/New_York"

string tz = TZConvert.WindowsToIana("Eastern Standard Time", "CA");
// result:  "America/Toronto"

More samples can be seen on the project’s website.

While an IANA time zone can be mapped to a single Windows time zone, the opposite is not true. Multiple IANA time zones can be mapped to a single Windows time zone. This is evidenced by the fact that Eastern Standard Time is mapped to both America/New York and America/Toronto in the examples above. Unless you specifically specify a country code and there is a match for a different zone in that nation, TimeZoneConverter will deliver the one that CLDR labels with “001,” sometimes known as the “golden zone.”

Note: Because this answer has changed over time, the comments below may or may not apply to the most recent iteration. For further information, look at the edit history. Thanks.

Answered by Matt Johnson-Pint

Solution #2

With the release of.NET 6, it is now feasible to interact with time zones across platforms, eliminating the need for manual workarounds.

On either platform, the TimeZoneInfo.FindSystemTimeZoneById(string) method takes either Windows or IANA time zones and translates them if necessary.

// Both of these will now work on any supported OS where ICU and time zone data are available.
TimeZoneInfo tzi1 = TimeZoneInfo.FindSystemTimeZoneById("AUS Eastern Standard Time");
TimeZoneInfo tzi2 = TimeZoneInfo.FindSystemTimeZoneById("Australia/Sydney");

Note that the.NET Core Alpine Linux-based Docker images do not come with the requisite tzdata installed by default, as stated in the link, therefore you’ll need to add it in your Dockerfile for this to function.

Answered by Tobias J

Solution #3

I realize this is an old question, but I had a use case that I thought I’d share because this was the most relevant topic I discovered when searching. I was working on a.NET Core app in a Docker linux container that would be deployed on a Windows server. So my docker linux container was just required to handle the Windows timezone names. I was able to get this to work without having to change my application code by doing the following:

cp /usr/share/zoneinfo/America/Chicago "/usr/share/zoneinfo/Central Standard Time"
cp /usr/share/zoneinfo/America/New_York "/usr/share/zoneinfo/Eastern Standard Time"
cp /usr/share/zoneinfo/America/Denver "/usr/share/zoneinfo/Mountain Standard Time"
cp /usr/share/zoneinfo/America/Los_Angeles "/usr/share/zoneinfo/Pacific Standard Time"

Then, in my.NET code, I was able to get the following to function without any changes: FindSystemTimeZoneById (TimeZoneInfo.FindSystemTimeZoneById) (“Central Standard Time”)

Answered by EverPresent

Post is based on