C# – How to use TimeZoneInfo

Time zones are complicated and their rules can change, so it makes sense to use a library when you’re dealing with them. One option in .NET is to use the built-in TimeZoneInfo class.

Here’s an example of using TimeZoneInfo to get the local system’s time zone:

var localTimeZone = TimeZoneInfo.Local;

Console.WriteLine($"Time zone display name: {localTimeZone.DisplayName}"); //same as .ToString()
Console.WriteLine($"Time zone id (Windows): {localTimeZone.Id}");
Code language: C# (cs)

This outputs:

Time zone display name: (UTC-05:00) Eastern Time (US & Canada)
Time zone id: Eastern Standard TimeCode language: plaintext (plaintext)

Note: The display name always show the base UTC offset (-05:00) instead of showing the current UTC offset based on daylight savings time. This can be misleading (this is what Windows shows!).

In this article, I’ll show several examples of using TimeZoneInfo.

Warning: They added support for IANA IDs in .NET 6. If you’re using a version prior to that, you’ll get a TimeZoneNotFoundException if you try to use an IANA ID. Use the Windows time zone ID if you’re on a version before .NET 6.

Get a time zone by ID

You can get a time zone by its Windows time zone ID (i.e. Eastern Standard Time) or with its IANA ID (i.e. America/Detroit).

Here’s an example of getting a time zone using its Windows time zone ID:

var easternTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");

Console.WriteLine($"Id: {easternTimeZone.Id}");
Console.WriteLine($"Display name: {easternTimeZone.DisplayName}");
Console.WriteLine($"Has IANA id? {easternTimeZone.HasIanaId}");
Code language: C# (cs)

This outputs:

Id: Eastern Standard Time
Display name: (UTC-05:00) Eastern Time (US & Canada)
Has IANA id? FalseCode language: plaintext (plaintext)

Here’s an example of getting a time zone using its IANA ID:

var detroitTimeZone = TimeZoneInfo.FindSystemTimeZoneById("America/Detroit");

Console.WriteLine($"Id: {detroitTimeZone.Id}");
Console.WriteLine($"Display name: {detroitTimeZone.DisplayName}");
Console.WriteLine($"Has IANA id? {detroitTimeZone.HasIanaId}");
Code language: C# (cs)

Warning: This only works in .NET 6 and above. If you’re on an earlier version, you’ll get a TimeZoneNotFoundException.

This outputs:

Id: America/Detroit
Display name: (UTC-05:00) Eastern Time (US & Canada)
Has IANA id? TrueCode language: plaintext (plaintext)

Note: The name ‘HasIanaId’ is a little misleading. It doesn’t mean “does this time zone have an IANA ID?” Instead, it means you use the IANA ID to lookup the time zone with TimeZoneInfo.FindSystemTimeZoneById().

To see all IANA IDs, I suggest checking out the wiki page List of tz database time zones (note: “tz database” and IANA mean the same thing).

Convert from one time zone to another

Here’s an example of converting a DateTimeOffset object from one time zone to another:

var eventTimeLocal = DateTimeOffset.Now;
var eventTimeLA = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(eventTimeLocal, "Pacific Standard Time");

Console.WriteLine($"Event local time: {eventTimeLocal}");
Console.WriteLine($"Event LA time: {eventTimeLA}");
Code language: C# (cs)

This outputs:

Event local time: 6/27/2022 3:09:43 PM -04:00
Event LA time: 6/27/2022 12:09:43 PM -07:00

If you already have the TimeZoneInfo object (such as if you looked it up), you can use TimeZoneInfo.ConvertTime() like this instead:

var usCentralTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
var centralTimeNow = TimeZoneInfo.ConvertTime(DateTimeOffset.Now, usCentralTimeZone);
Code language: C# (cs)

Convert from Windows time zone ID to IANA ID

In .NET 6, they added methods for converting between Windows time zone IDs and IANA IDs.

Here’s an example of converting from a Windows time zone ID to an IANA ID:

var windowsTimeZoneID = TimeZoneInfo.Local.Id;

if (TimeZoneInfo.TryConvertWindowsIdToIanaId(windowsTimeZoneID, out string? ianaId))
{
	Console.WriteLine($"Windows time zone id ({windowsTimeZoneID}) = IANA ID ({ianaId})");
}
Code language: C# (cs)

This outputs:

Windows time zone id (Eastern Standard Time) = IANA ID (America/New_York)Code language: plaintext (plaintext)

And vice versa – convert from an IANA ID to a Windows time zone ID:

var ianaIdFromClient = "America/Detroit";

if (TimeZoneInfo.TryConvertIanaIdToWindowsId(ianaIdFromClient, out string? windowsId))
{
	Console.WriteLine($"Windows time zone id ({windowsTimeZoneID}) = IANA ID ({ianaIdFromClient})");
}
Code language: C# (cs)

This outputs:

Windows time zone id (Eastern Standard Time) = IANA ID (America/Detroit)Code language: plaintext (plaintext)

As you can see, Windows time zone IDs map to one or more IANA IDs. In the examples above, Eastern Standard Time mapped to both America/New_York and America/Detroit (this is my actual one). The converter method only returns one IANA ID. To see a full list of IANA IDs, refer to this wiki page – List of tz database time zones (note: “tz database” is the same thing as “IANA”).

Get a list of all system time zones

Use TimeZoneInfo.GetSystemTimeZones() to get all of the system’s time zones (as TimeZoneInfo objects), like this:

foreach (var timezone in TimeZoneInfo.GetSystemTimeZones())
{
	Console.WriteLine(timezone.Id);
}
Code language: C# (cs)

Here’s a snippet of what this outputs:

...

Hawaiian Standard Time
Marquesas Standard Time
Alaskan Standard Time
...Code language: plaintext (plaintext)

Get IANA IDs for all system time zones

Let’s say you want to generate a list of system time zones and show their IANA IDs (instead of Windows time zone IDs). You can use a combination of GetSystemTimeZones() and TryConvertWindowsIdToIanaId() (added in .NET 6) to do this. Here’s an example:

var timeZoneList = TimeZoneInfo.GetSystemTimeZones().Select(tz =>
{
	TimeZoneInfo.TryConvertWindowsIdToIanaId(tz.Id, out string? IanaId);
	return new
	{
		IanaId,
		tz.DisplayName
	};
});

foreach (var timeZone in timeZoneList)
{
	Console.WriteLine($"{timeZone.IanaId} - {timeZone.DisplayName}");
}
Code language: C# (cs)

Note: Of course, you can always add your own class with the desired properties instead of using an anonymous type like this.

Here’s a snippet of what this returns:

...
America/Los_Angeles - (UTC-08:00) Pacific Time (US & Canada)
America/Phoenix - (UTC-07:00) Arizona
America/Chihuahua - (UTC-07:00) Chihuahua, La Paz, Mazatlan
America/Denver - (UTC-07:00) Mountain Time (US & Canada)
...Code language: plaintext (plaintext)

Remember that Windows time zone IDs map to multiple IANA IDs, but the converter methods only return one of the mapped IANA IDs. This means you can really only get a subset of IANA IDs using this approach. It would be nice if this would return a collection of all mapped IANA IDs.

4 thoughts on “C# – How to use TimeZoneInfo”

  1. var timeZoneList = TimeZoneInfo.GetSystemTimeZones().Select(tz =>
    {
    TimeZoneInfo.TryConvertWindowsIdToIanaId(tz.Id, out string? IanaId);
    return new
    {
    IanaId,
    tz.DisplayName
    };
    });

    Your code work in Windows OS only right?
    As I know, the returned list of TimeZoneInfo.GetSystemTimeZones() depends on the OS. If it is windows OS, it returns Windows time zones. Otherwise, it returns IANA time zones. Hence, TryConvertWindowsIdToIanaId in this case cannot work correctly.

    How could we handle this in all OS? .NetCore can run in all OSs so it will be great if we can do it not only on Windows.

    Thanks

    Reply
    • Yes, that example is specifically for converting Windows time zone names to IANA time zone names. The TryConvertWindowsIdToIanaId() method is specific to Windows.

      You can check which OS you’re running in with RuntimeInformation.IsOSPlatform(OSPlatform.Windows) (in System.Runtime.InteropServices). So in this example, you could conditionally call TryConvertWindowsIdToIanaId() if you’re in Windows.

      For example:

      var timeZoneList = TimeZoneInfo.GetSystemTimeZones();

      if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
      {
          Convert timeZoneList ids/names from Windows to IANA using TryConvertWindowsIdToIanaId()
      }

      I hope this helps answer your question.

      Reply

Leave a Comment