如何在Xamarin中获得Noda Time返回“ America / Los_Angeles”?

时间:2018-10-02 12:39:40

标签: c# xamarin timezone nodatime

我正在使用Noda Time以Xamarin Forms形式获取设备上的本地时区。我们使用下面的代码将其返回。

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

但是,如果您将手机的位置设置为美国西海岸的任何位置,它将返回“ America / Tijuana”。这给我们带来了一个问题,如果在您的位置设置为L.A时返回“ America / Los_Angeles”(有效的ID)之类的信息,则可以解决。

有什么想法吗?我如何才能使图书馆返回更准确的ID?

2 个答案:

答案 0 :(得分:7)

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

我们向TimeZoneInfo询问其在该时间间隔(IANA时区中的任何有过渡的每个瞬间)的UTC偏移量的想法。然后,我们根据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的代码)均表现合理。

如注释中所建议,您可能想使用特定于平台的代码来解决此问题:iOS上Foundation.NSTimeZone.LocalTimeZone.Name属性,也许还有Java.Util.TimeZone.Default.ID属性在Android上。

答案 1 :(得分:0)

此问题可以通过以下方式解决:

例如: 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;