C# – Get a time zone’s display name with the current date’s UTC offset

A time zone’s UTC offset can change based on the time of year due to daylight savings time. One problem with the TimeZoneInfo class is that TimeZoneInfo.DisplayName always shows the base UTC offset, even if the current date is in daylight savings time. This may be confusing to users (and this is the same thing Windows shows!).

Here’s an example of the problem:

Console.WriteLine($"Current local date/time: {DateTimeOffset.Now}"); Console.WriteLine($"Local time zone: {TimeZoneInfo.Local.DisplayName}");
Code language: C# (cs)

This outputs:

Current local date/time: 6/27/2022 4:40:00 PM -04:00 Local time zone: (UTC-05:00) Eastern Time (US & Canada)
Code language: plaintext (plaintext)

Notice that the time zone’s display name shows the base UTC offset of -05:00, even though the current date’s UTC offset is -04:00 (due to daylight savings time).

What if you want the time zone’s display name to show the current date’s UTC offset instead? Here’s one way to do it:

  • Get the time zone’s current UTC offset.
  • Convert it to the UTC format – i.e. (UTC-04:00).
  • Replace the UTC part of the time zone’s display name with the new UTC offset string.

In other words, you start with (UTC-05:00) Eastern Time (US & Canada) and end up with (UTC-04:00) Eastern Time (US & Canada).

I’ll show the code for this below, along with a few scenarios of using it.

Code

Here’s an implementation of the algorithm explained above for getting a time zone’s display name with the current date’s UTC offset. This is put into an extension method for convenience.

public static class TimeZoneInfoExtensions { public static string GetDisplayNameWithCurrentOffset(this TimeZoneInfo timezone, DateTimeOffset date) { if (!timezone.SupportsDaylightSavingTime) return timezone.DisplayName; //Example: Removes (UTC-04:00) var displayNameWithoutOffset = timezone.DisplayName.Remove(0, 11); var currentOffset = TimeZoneInfo.ConvertTime(date, timezone).Offset; var currentOffsetHHMM = currentOffset.ToString("hh\\:mm"); if (currentOffset < TimeSpan.Zero) { return $"(UTC-{currentOffsetHHMM}){displayNameWithoutOffset}"; } else { return $"(UTC+{currentOffsetHHMM}){displayNameWithoutOffset}"; } } }
Code language: C# (cs)

Note: You could try to apply daylight savings rules yourself, but I would suggest letting TimeZoneInfo do the work for you.

I’ll show examples of using this code in three different scenarios. For comparison purposes, I’ll show both TimeZoneInfo.DisplayName and the display name from GetDisplayNameWithCurrentOffset().

Scenario – Display local time zone with the current UTC offset

Here’s an example of using GetDisplayNameWithCurrentOffset() with the local time zone and the current date:

var defaultDisplayName = TimeZoneInfo.Local.DisplayName; Console.WriteLine($"Display Name (base offset): {defaultDisplayName}"); var localNow = DateTimeOffset.Now; var displayNameWithCurrentOffset = TimeZoneInfo.Local.GetDisplayNameWithCurrentOffset(localNow); Console.WriteLine($"Display Name (current offset): {displayNameWithCurrentOffset}");
Code language: C# (cs)

This outputs:

Display Name (base offset): (UTC-05:00) Eastern Time (US & Canada) Display Name (current offset): (UTC-04:00) Eastern Time (US & Canada)
Code language: plaintext (plaintext)

Scenario – Get all system time zones and display them with current UTC offsets

This example loops through all system time zones and uses GetDisplayNameWithCurrentOffset() to display them with their current UTC offset:

var localNow = DateTimeOffset.Now; foreach (var timeZone in TimeZoneInfo.GetSystemTimeZones()) { var defaultDisplayName = timeZone.DisplayName; Console.WriteLine($"Display Name (base offset): {defaultDisplayName}"); var displayNameWithCurrentOffset = timeZone.GetDisplayNameWithCurrentOffset(localNow); Console.WriteLine($"Display Name (current offset): {displayNameWithCurrentOffset}"); }
Code language: C# (cs)

Note: You can use this as a starting point for generating time zone lists to show to the user.

Here’s a small snippet of the output:

... Display Name (base offset): (UTC-05:00) Eastern Time (US & Canada) Display Name (current offset): (UTC-04:00) Eastern Time (US & Canada) ... Display Name (base offset): (UTC+08:00) Perth Display Name (current offset): (UTC+08:00) Perth ...
Code language: plaintext (plaintext)

This highlights a few interesting examples about the complexity of time zones (and why you should definitely use a library like TimeZoneInfo when dealing with them):

  • US Eastern Time is in the Northern Hemisphere, and is currently in daylight savings time (because it’s summer).
  • Australia is in the Southern Hemisphere, hence its Perth time zone is not currently in daylight savings time (because it’s winter).

Furthermore, if you look at all of the results, you’ll realize not all time zones have daylight savings rules (and the ones that do don’t have the same schedules).

Scenario – Get a time zone by ID and display it with the current UTC offset

Here’s an example of looking up a time zone by its ID, and then using GetDisplayNameWithCurrentOffset() to get its display name with the current UTC offset:

var pacificTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"); var defaultDisplayName = pacificTimeZone.DisplayName; Console.WriteLine($"Display Name (base offset): {defaultDisplayName}"); var displayNameWithCurrentOffset = pacificTimeZone.GetDisplayNameWithCurrentOffset(DateTimeOffset.Now); Console.WriteLine($"Display Name (current offset): {displayNameWithCurrentOffset}");
Code language: C# (cs)

This outputs the following:

Display Name (base offset): (UTC-08:00) Pacific Time (US & Canada) Display Name (current offset): (UTC-07:00) Pacific Time (US & Canada)
Code language: plaintext (plaintext)

Leave a Comment