当前时区为 UTC 时,TimeZoneInfo.GetSystemTimeZones 不包含 TimeZoneInfo.Local

TimeZoneInfo.GetSystemTimeZones does not contain TimeZoneInfo.Local when current timezone is UTC

在我的 linux 机器上,时区设置为 UTC。

[root@(none) /]# date
Tue Sep 22 16:11:12 UTC 2020

我曾经运行一个程序

TimeZoneInfo localZone = TimeZoneInfo.Local; 
      ReadOnlyCollection<TimeZoneInfo> zones = TimeZoneInfo.GetSystemTimeZones ();
      foreach (TimeZoneInfo zoneVal in zones) {
          if (localZone.StandardName == zoneVal.StandardName) {
              Console.WriteLine("local zone found!!"); //this is not printing
          }
      }

如果我 运行 使用 dotnet-core 2.1,这个程序工作正常。但是,如果我 运行 使用 mono 6.0.0.327,它无法在系统时区中找到 localZone。

有没有办法让它在不从 UTC 更改当前时区并且不更改为 dotnet 的情况下工作?

StandardName属性不识别时区。它是一个本地化的字符串,用于人类显示,然后仅在夏令时未生效时才生效,即使如此 sometimes they are quirky.

当您要识别时区时,请使用Id 属性,而不是StandardName

此外:

  • 如果你想要UTC,那么使用TimeZoneInfo.Utc

  • 如果你想要本地时区,那么使用TimeZoneInfo.Local

  • 如果要查找时区,请使用 TimeZoneInfo.FindSystemTimeZoneById 并将所需时区的 Id 传递给它。当 Linux 上 运行 时,ID 将是 IANA time zone names,当 Windows 上 运行 时,ID 将是 Windows 时区标识符。

  • 如果您想编写与平台无关的代码,请使用我的 TimeZoneConverter 库中的 TZConvert.GetTimeZoneInfo

  • 如果你真的需要匹配TimeZoneInfo对象,使用Equals方法,它比较Id和调整规则(对于边您可能已经构建了自定义时区,或在 Windows 上禁用了 DST 的情况)。请参阅 the docs here备注 部分。例如:

    if (localZone.Equals(zoneVal))
    {
        ...
    }
    
  • 另请注意 TimeZoneInfo.LocalTimeZoneInfo.FindSystemTimeZoneById(TimeZoneInfo.Local.Id) 之间存在差异,尤其是在 Windows 上禁用 DST 时。 See these other docs for more details.

扩展 Matt 的答案,这是最终帮助我的答案,下面是我的代码片段,Id 属性 是关键。您需要安装“TimeZoneConverter”NuGet。下面的代码片段适用于 Windows & Linux with .NET Core 3.1:

var tz = TZConvert.GetTimeZoneInfo("Any TimeZone Name");

TimeZoneInfo tst = TimeZoneInfo.FindSystemTimeZoneById(tz.Id);