TimeZoneInfo in .NET Core when hosting on unix (nginx)

C#.NetNginxTimezone.Net Core

C# Problem Overview


For example, when I try to do the following.

TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time")

I get the error, that the TimeZone is not available on the local computer. When I run this locally it works, but there I run it on windows. When deployed it runs on a Unix machine in Nginx. I can see that FindSystemTimeZoneById is looking in the wrong folder when it comes to Unix. Is there any way to make this work?

C# Solutions


Solution 1 - C#

.Net Core using system timezone. Unfortunately Windows and Linux have different timezone system. Now you have two ways:

Solution 2 - C#

Working of off the previous answer, we can avoid the expensive try/catch by checking which OS we're running on:

using System;
using System.Runtime.InteropServices;

TimeZoneInfo easternStandardTime;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
  easternStandardTime = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
}
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
  easternStandardTime = TimeZoneInfo.FindSystemTimeZoneById("America/New_York");
}
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
  easternStandardTime = TimeZoneInfo.FindSystemTimeZoneById("America/New_York");
}

Solution 3 - C#

Can you please try this?

   TimeZoneInfo easternZone;
        try
        {
            easternZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
        }
        catch (TimeZoneNotFoundException)
        {
            easternZone = TimeZoneInfo.FindSystemTimeZoneById("America/New_York");
        }

You can review the list of IANA time zones here https://en.wikipedia.org/wiki/List_of_tz_database_time_zones

Solution 4 - C#

If you want to try a Windows time zone and then fallback on a IANA one if the Windows one doesn't exist:

var tzi  = TimeZoneInfo.GetSystemTimeZones().Any(x => x.Id == "Eastern Standard Time") ? 
    TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time") : 
    TimeZoneInfo.FindSystemTimeZoneById("America/New_York");

Solution 5 - C#

I was able to support this use-case in my development docker image by doing the following:

cp /usr/share/zoneinfo/America/Los_Angeles "/usr/share/zoneinfo/Pacific Standard Time"

Obviously, I don't think that would be a good idea for production deployments. But it might help in some scenarios.

Solution 6 - C#

Starting with .NET 6, it is finally possible to work with time zones in a cross-platform manner.

The TimeZoneInfo.FindSystemTimeZoneById(string) method automatically accepts either Windows or IANA time zones on either platform and convert them if needed.

// 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, as specified on the link, the .NET Core Alpine Linux-based Docker images do not have the necessary tzdata installed by default, so it must be installed in your Dockerfile for this to work correctly.

Solution 7 - C#

Quick and dirty solution: serialize your TimeZoneInfo with ToSerializedString in a dummy app on Windows, save the output, then deserialize with FromSerializedString where you need it.

On Windows:

Console.WriteLine(TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time"));

Output:

Eastern Standard Time;-300;(UTC-05:00) Eastern Time (US & Canada);Eastern Standard Time;Eastern Daylight Time;[01:01:0001;12:31:2006;60;[0;02:00:00;4;1;0;];[0;02:00:00;10;5;0;];][01:01:2007;12:31:9999;60;[0;02:00:00;3;2;0;];[0;02:00:00;11;1;0;];];

Then:

// TimeZoneInfo is immutable
public static readonly TimeZoneInfo EST = TimeZoneInfo.FromSerializedString(
            "Eastern Standard Time;-300;(UTC-05:00) Eastern Time (US & Canada);Eastern Standard Time;Eastern Daylight Time;[01:01:0001;12:31:2006;60;[0;02:00:00;4;1;0;];[0;02:00:00;10;5;0;];][01:01:2007;12:31:9999;60;[0;02:00:00;3;2;0;];[0;02:00:00;11;1;0;];];");

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionnoshitsherlockView Question on Stackoverflow
Solution 1 - C#J. DoeView Answer on Stackoverflow
Solution 2 - C#UliView Answer on Stackoverflow
Solution 3 - C#Alvaro BardajiView Answer on Stackoverflow
Solution 4 - C#samView Answer on Stackoverflow
Solution 5 - C#EverPresentView Answer on Stackoverflow
Solution 6 - C#Tobias JView Answer on Stackoverflow
Solution 7 - C#fidkeView Answer on Stackoverflow