IDateTimeZoneSource.MapTimeZoneId 的 Noda 时区问题
Noda Timezone issue with IDateTimeZoneSource.MapTimeZoneId
我正在尝试将 Windows 转换为 IANA 时区,下面是大部分时间都有效的代码。但是当windows时id="Turks & Caicos"那么下面的代码returns NULL。我正在使用 NODATIME 版本 1.3.1
Public Function ConvertID_WindowsToIana(strWindowsZoneID As String) As String
If strWindowsZoneID.Equals("UTC", StringComparison.OrdinalIgnoreCase) Then
Return "Etc/UTC"
End If
Dim tzdbSource = NodaTime.TimeZones.TzdbDateTimeZoneSource.[Default]
Dim tzi = TimeZoneInfo.MapTimeZoneId(strWindowsZoneID)
Return tzdbSource.CanonicalIdMap(tzi)
End Function
此处当 tzi = -4:00 特克斯和凯科斯群岛时,在这种情况下 return 为 NULL。
现在,当我更新到版本 2.2.3 时,我认为它会修复这些问题,但根据文档
现在该函数将 "Position Of Current String" 作为参数。
所以我的代码如下所示:
Public Function ConvertID_WindowsToIana(strWindowsZoneID As String) As String
Dim tzi = TimeZoneInfo.FindSystemTimeZoneById(strWindowsZoneID)
Dim tzid = tzdbSource.GetSystemDefaultId(WHAT TO PUT HERE)
// some logic
End Function
问题 1: 为什么我的第一个代码不适用于 "Turks and Caicos"。
问题 2: 我更新后认为它会解决该问题,但现在该功能已消失并被替换,我不知道该用什么。请帮助我。
P.S: 对于东部和许多其他时区,第一个代码片段 工作正常。
GetSystemDefaultId
不会替换 MapTimeZoneId
的所有功能 - 您不想在此处调用它。
相反,请使用 tzdbSource.WindowsMapping
获取 WindowsZones
,然后您可以使用它来查找 TZDB ID。这是一些示例代码:
using System;
using NodaTime.TimeZones;
public class Test
{
static void Main()
{
var source = TzdbDateTimeZoneSource.Default;
string windowsId = "Turks And Caicos Standard Time";
var mapping = source.WindowsMapping.PrimaryMapping;
if (mapping.TryGetValue(windowsId, out string tzdbId))
{
Console.WriteLine($"Mapped to {tzdbId}");
}
else
{
Console.WriteLine("Not found");
}
}
}
另一种方法是使用 Matt Johnson 的 TimeZoneConverter 程序包,它可以进一步简化事情。如果您在其他地方使用 Noda Time,坚持使用 Noda Time 可能是有意义的,但如果您仅使用它进行时区 ID 转换,TimeZoneConverter 是更好的选择。
至于为什么 "Turks and Caicos" 不起作用 - 我假设您的意思是 "Turks And Caicos Standard Time" 作为 ID。那只是在 CLDR v30 中引入了 CLDR 映射数据,它比 1.3.1 发布晚了一年多。如果您更新到 1.3.5 或 1.4.2,这两个都应该没问题。
我正在尝试将 Windows 转换为 IANA 时区,下面是大部分时间都有效的代码。但是当windows时id="Turks & Caicos"那么下面的代码returns NULL。我正在使用 NODATIME 版本 1.3.1
Public Function ConvertID_WindowsToIana(strWindowsZoneID As String) As String
If strWindowsZoneID.Equals("UTC", StringComparison.OrdinalIgnoreCase) Then
Return "Etc/UTC"
End If
Dim tzdbSource = NodaTime.TimeZones.TzdbDateTimeZoneSource.[Default]
Dim tzi = TimeZoneInfo.MapTimeZoneId(strWindowsZoneID)
Return tzdbSource.CanonicalIdMap(tzi)
End Function
此处当 tzi = -4:00 特克斯和凯科斯群岛时,在这种情况下 return 为 NULL。
现在,当我更新到版本 2.2.3 时,我认为它会修复这些问题,但根据文档
现在该函数将 "Position Of Current String" 作为参数。
所以我的代码如下所示:
Public Function ConvertID_WindowsToIana(strWindowsZoneID As String) As String
Dim tzi = TimeZoneInfo.FindSystemTimeZoneById(strWindowsZoneID)
Dim tzid = tzdbSource.GetSystemDefaultId(WHAT TO PUT HERE)
// some logic
End Function
问题 1: 为什么我的第一个代码不适用于 "Turks and Caicos"。
问题 2: 我更新后认为它会解决该问题,但现在该功能已消失并被替换,我不知道该用什么。请帮助我。
P.S: 对于东部和许多其他时区,第一个代码片段 工作正常。
GetSystemDefaultId
不会替换 MapTimeZoneId
的所有功能 - 您不想在此处调用它。
相反,请使用 tzdbSource.WindowsMapping
获取 WindowsZones
,然后您可以使用它来查找 TZDB ID。这是一些示例代码:
using System;
using NodaTime.TimeZones;
public class Test
{
static void Main()
{
var source = TzdbDateTimeZoneSource.Default;
string windowsId = "Turks And Caicos Standard Time";
var mapping = source.WindowsMapping.PrimaryMapping;
if (mapping.TryGetValue(windowsId, out string tzdbId))
{
Console.WriteLine($"Mapped to {tzdbId}");
}
else
{
Console.WriteLine("Not found");
}
}
}
另一种方法是使用 Matt Johnson 的 TimeZoneConverter 程序包,它可以进一步简化事情。如果您在其他地方使用 Noda Time,坚持使用 Noda Time 可能是有意义的,但如果您仅使用它进行时区 ID 转换,TimeZoneConverter 是更好的选择。
至于为什么 "Turks and Caicos" 不起作用 - 我假设您的意思是 "Turks And Caicos Standard Time" 作为 ID。那只是在 CLDR v30 中引入了 CLDR 映射数据,它比 1.3.1 发布晚了一年多。如果您更新到 1.3.5 或 1.4.2,这两个都应该没问题。