在unix上托管时,.NET Core中的TimeZoneInfo(nginx)

nos*_*ock 18 .net c# timezone nginx .net-core

例如,当我尝试执行以下操作时.

TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time")
Run Code Online (Sandbox Code Playgroud)

我收到错误,该错误TimeZone在本地计算机上不可用.当我在本地运行它可以工作,但我在Windows上运行它.部署时,它在Nginx的Unix机器上运行.我可以看到,FindSystemTimeZoneById在涉及到Unix时,它正在寻找错误的文件夹.有没有办法让这项工作?

Uli*_*Uli 28

处理上一个答案,我们可以try/catch通过检查我们正在运行的操作系统来避免昂贵的费用:

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))
{
  throw new NotImplementedException("I don't know how to do a lookup on a Mac.");
}
Run Code Online (Sandbox Code Playgroud)

  • 您好,我在哪里可以找到 Windows 和 Linux timezoneID 的并排比较?太难找了。我想要的只是找到 'Mountain Standard Time' 的 linux 等效值 (2认同)
  • 如果是 OSX,则时区称为“我们亲爱的先知和远见者的出生地 +08:30” (2认同)

Tob*_*s J 23

从 .NET 6 开始,终于可以跨平台方式处理时区了。

TimeZoneInfo.FindSystemTimeZoneById(string)方法自动接受任一平台上的 Windows 或 IANA 时区,并根据需要进行转换。

// 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");
Run Code Online (Sandbox Code Playgroud)

请注意,正如链接中所指定的,默认情况下,基于 .NET Core Alpine Linux 的 Docker 映像没有tzdata安装必要的工具,因此必须将其安装在您的计算机中Dockerfile才能正常工作。


J. *_*Doe 17

.Net Core使用系统时区.不幸的是,Windows和Linux有不同的时区系统.现在你有两种方式:

  • 这是Unix上.NET Core的当前限制.请参阅[此处的GitHub问题](https://github.com/dotnet/corefx/issues/2538).您需要在Windows上传递与Unix不同的时区ID.该问题被标记为"争抢".欢迎提交;). (6认同)

小智 14

如果您想尝试使用 Windows 时区,然后在 Windows 时区不存在的情况下回退到 IANA 时区:

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


小智 10

你可以试试看吗?

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

您可以在此处查看IANA时区列表https://en.wikipedia.org/wiki/List_of_tz_database_time_zones

  • 这不是有史以来最好的解决方案,但如果失败,他会使用另一个假设您正在使用 Linux 的解决方案,反之亦然,并且它有效。 (3认同)
  • 请解释这如何以及为什么解决所描述的问题。谢谢! (2认同)

Eve*_*ent 10

通过执行以下操作,我能够在我的开发 docker 映像中支持此用例:

cp /usr/share/zoneinfo/America/Los_Angeles "/usr/share/zoneinfo/Pacific Standard Time"
Run Code Online (Sandbox Code Playgroud)

显然,我认为这对于生产部署来说不是一个好主意。但在某些情况下它可能会有所帮助。


小智 5

快速而肮脏的解决方案:在 Windows 上的虚拟应用程序中TimeZoneInfo使用ToSerializedString序列化,保存输出,然后在需要的地方使用FromSerializedString反序列化。

在 Windows 上:

Console.WriteLine(TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time").ToSerializedString());
Run Code Online (Sandbox Code Playgroud)

输出:

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;];];
Run Code Online (Sandbox Code Playgroud)

然后:

// 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;];];");
Run Code Online (Sandbox Code Playgroud)