如何让 Xamarin 中的 Noda Time 达到 return "America/Los_Angeles"?

How can I get Noda Time in Xamarin to return "America/Los_Angeles"?

我正在使用 Noda Time 在 Xamarin Forms 中获取设备上的本地时区。我们使用下面的代码来 return 它。

NodaTime.DateTimeZoneProviders.Tzdb.GetSystemDefault().Id;

但是,如果您将 phone 的位置设置为美国西海岸的任何地方,它 returns "America/Tijuana." 这会给我们带来一个问题,即当您的位置设置为 L.A.

时,如果它 return 编辑了类似 "America/Los_Angeles" 的内容(这是一个有效的 ID),则已解决

有什么想法吗?我怎样才能让图书馆 return 更准确的 Id?

在某些平台上,根据您使用的 Noda Time 版本,系统时区 ID 不可用,因此我们必须猜测。我们根据从当年的 1 月 1 日到 5 年后的 1 月 1 日的时区转换来执行此操作。 (这是生产代码中唯一使用系统时钟的地方。)

我们向 TimeZoneInfo 询问其关于该间隔内许多不同时刻的 UTC 偏移的想法(IANA 时区的 any 的每个时刻都有一个过渡)。然后我们 "score" 每个 IANA 时区对照 TimeZoneInfo 值,以查看瞬间 return 相同 UTC 偏移量的比例。我们 return 匹配次数最多的时区 ID,只要它至少是匹配次数的 70%。

在您的情况下,America/Tijuana 和 America/Los_Angeles 在 2018-2022 的 5 年中具有相同的过渡。在 tzvalidate 格式中:

2018-03-11 10:00:00Z -07:00:00 daylight PDT
2018-11-04 09:00:00Z -08:00:00 standard PST
2019-03-10 10:00:00Z -07:00:00 daylight PDT
2019-11-03 09:00:00Z -08:00:00 standard PST
2020-03-08 10:00:00Z -07:00:00 daylight PDT
2020-11-01 09:00:00Z -08:00:00 standard PST
2021-03-14 10:00:00Z -07:00:00 daylight PDT
2021-11-07 09:00:00Z -08:00:00 standard PST
2022-03-13 10:00:00Z -07:00:00 daylight PDT
2022-11-06 09:00:00Z -08:00:00 standard PST

Noda Time 无法区分这 5 年期间的两个时区,因此它 return 是第一个找到的时区。 (未定义它首先找到哪个 - 这是我们可能希望通过按 ID 对时区进行排序来解决的问题。我会为此提交一个问题。)

我希望这有助于解释您所看到的 - 它并没有解决问题,但它表明所有代码(您的和 Noda Time 的代码)在可用信息有限的情况下都表现合理。

如评论中所建议,您可能需要使用特定于平台的代码来解决此问题:Android 上 Foundation.NSTimeZone.LocalTimeZone on iOS and maybe the .ID property of Java.Util.TimeZone.Default.Name 属性。

这个问题可以这样解决:

例如: 1.在App.xaml.cs

public partial class App : Application
{

   public static string timeZoneName { get; set; } = string.Empty;

    public App()
    {
        var timezone = string.Empty;
        if (Device.RuntimePlatform == Device.Android)
        {
                timezone = TimeZoneInfo.Local.DisplayName;
        }
        else if (Device.RuntimePlatform == Device.iOS)
        {
                timezone = App.timeZoneName;
        }
    }

}

2。 AppDelegate.cs

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
     global::Xamarin.Forms.Forms.Init();
     App.timeZoneName = NSTimeZone.LocalTimeZone.Name;
     LoadApplication(new App());
     return base.FinishedLaunching(app, options);
}
  1. 在 ViewModel 或任何 class

var timezone = App.timeZoneName;