【问题标题】:How can I get Noda Time in Xamarin to return "America/Los_Angeles"?如何让 Xamarin 中的 Noda Time 返回“America/Los_Angeles”?
【发布时间】:2019-03-07 14:13:07
【问题描述】:

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

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

但是,如果您将手机的位置设置为美国西海岸的任何地方,它会返回“America/Tijuana”。这给我们带来了一个问题,如果它在您的位置设置为 L.A. 时返回类似“America/Los_Angeles”(这是一个有效的 Id)之类的内容,将会得到解决。

有什么想法吗?如何让图书馆返回更准确的 ID?

【问题讨论】:

  • 哪款手机,操作系统,手机的时区设置是什么?
  • 请注意,America/Tijuana 也是有效时区,但适用于墨西哥。
  • 另外,TimeZoneInfo.Local.Id 在此手机上返回什么?它是否返回"America/Tijuana"?还是返回"Local"
  • (如果您有兴趣,可以深入了解starting here 的源代码以查看遵循的代码路径。我的猜测是您的环境返回“Local”,因此沿着@ 987654329@ 路径。)
  • 所以,它返回“本地”证实了我的猜测。 NodaTime 无法直接解决这个问题。它所能做的最好的就是猜测。为了获得更好的结果,您可能需要使用本机特定于平台的 API。我没有做很多 Xamrin 的东西,所以试试这个,让我知道 - 但是你有没有可能在 iOS 上使用 Foundation.NSTimeZone.LocalTimeZone.Name 属性或者 Java.Util.TimeZone.Default.ID 属性在安卓上?

标签: c# xamarin timezone nodatime


【解决方案1】:

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

我们向TimeZoneInfo 询问其关于该时间间隔内许多不同时刻的 UTC 偏移量的想法(任何 IANA 时区发生转换的每一时刻)。然后,我们根据TimeZoneInfo 值对每个 IANA 时区进行“评分”,以查看有多少瞬间返回相同的 UTC 偏移量。我们返回匹配次数最多的时区的 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 年期间的两个时区,因此它返回它首先找到的那个。 (不确定它首先找到哪个 - 这可能是我们希望通过按 ID 排序时区来解决的问题。我会为此提出问题。)

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

根据 cmets 中的建议,您可能希望使用特定于平台的代码来解决此问题:iOS 上 Foundation.NSTimeZone.LocalTimeZone.Name 属性和 Android 上 Java.Util.TimeZone.Default.ID 属性。

【讨论】:

    【解决方案2】:

    这个问题可以这样解决:

    例如: 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 或任何类中

    var timezone = App.timeZoneName;

    【讨论】:

      猜你喜欢
      • 2019-09-01
      • 2014-06-08
      • 2020-03-24
      • 1970-01-01
      • 2020-09-28
      • 2012-04-22
      • 1970-01-01
      • 1970-01-01
      • 2023-01-18
      相关资源
      最近更新 更多