如何让 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);
}
- 在 ViewModel 或任何 class
var timezone = App.timeZoneName;
我正在使用 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);
}
- 在 ViewModel 或任何 class
var timezone = App.timeZoneName;