在 C# 中使用国家名称、日期时间和时区偏移值获取 ZoneId
Get ZoneId using country name, datetime and timezone offset values in c#
我有日期时间(yyyy-MM-ddTHH:mm:ss)、时区偏移值(K 即 -/+HH:mm)和国家/地区名称,并且想从我的网站中的这些值中获取 IANA 格式的 ZoneId API.
例如:
public static string FetchZoneID(string dateTime, string offset, string countryName)
{
//fetch zoneID
return zoneId;
}
价值
dateTime = "2020-02-06T06:11:01", offset = "+13:00", countryName = "New Zealand"
我应该得到
zoneId = "Pacific/Auckland"
以及值
dateTime = "2020-05-06T06:11:01", offset = "+12:00", countryName = "New Zealand"
我应该得到(由于 DST)
zoneId = "Pacific/Auckland"
目前使用 NodaTime,我能够获取特定国家/地区的所有 zoneId,但无法弄清楚如何根据日期时间和偏移值过滤这些。
var zoneIds = TzdbDateTimeZoneSource.Default.ZoneLocations.Where(x => x.CountryName == countryName)
.Select(x => x.ZoneId);
有人可以帮我解决这个问题吗?
注意:如果多个 zoneId 符合给定偏移量的条件,将使用第一个值。
我将稍微更改您的方法签名,并展示您如何可以列出所有 给定国家/地区的可能时区 ID,其中偏移量与特定本地日期相匹配和时间:
public static ICollection<string> FetchZoneIds(OffsetDateTime dateTime, string countryCode)
{
return TzdbDateTimeZoneSource.Default.ZoneLocations
.Where(x => x.CountryCode == countryCode)
.Select(x => dateTime.InZone(DateTimeZoneProviders.Tzdb[x.ZoneId]))
.Where(x => x.Offset == dateTime.Offset)
.Select(x => x.Zone.Id)
.ToList();
}
这里有一个小测试方法来说明使用字符串输入调用并转储到输出:
private static void Test(string dtoString, string countryCode)
{
Console.WriteLine($"{dtoString} ({countryCode})");
var offsetDateTime = OffsetDateTimePattern.GeneralIso.Parse(dtoString).Value;
var zoneIds = FetchZoneIds(offsetDateTime, countryCode);
foreach (var zoneId in zoneIds)
{
Console.WriteLine(zoneId);
}
Console.WriteLine();
}
您的第一个示例给出了单一的预期结果:
Test("2020-02-06T06:11:01+13:00", "NZ");
2020-02-06T06:11:01+13:00 (NZ)
Pacific/Auckland
你的第二个例子也是:
Test("2020-05-06T06:11:01+12:00", "NZ");
2020-05-06T06:11:01+12:00 (NZ)
Pacific/Auckland
但看看这里发生了什么:
Test("2020-11-01T01:00:00-05:00", "US");
2020-11-01T01:00:00-05:00 (US)
America/New_York
America/Detroit
America/Kentucky/Louisville
America/Kentucky/Monticello
America/Indiana/Indianapolis
America/Indiana/Vincennes
America/Indiana/Winamac
America/Indiana/Marengo
America/Indiana/Petersburg
America/Indiana/Vevay
America/Chicago
America/Indiana/Tell_City
America/Indiana/Knox
America/Menominee
America/North_Dakota/Center
America/North_Dakota/New_Salem
America/North_Dakota/Beulah
重要的是,请注意结果中有东部时间和中部时间的条目,主要是America/New_York
和America/Chicago
。怎么可能?
不,这不是错误。 You can verify it here。在美国,夏令时不是一下子就来的。它从东到西一次走一个时区。因此,当回退过渡发生在东部时区(2:00 EDT 变为 1:00 EST)时,中部时区仍为 1:00 EDT。它不会再过渡一个小时。换句话说,它 1:00 在 EST 和 CDT 中同时具有 UTC-5 偏移量。
如果你不关心这些事情,当然你可以做一个.FirstOrDefault()
(当没有匹配时默认是一个null
字符串)。但你可能确实会遇到像这样的边缘情况。
我有日期时间(yyyy-MM-ddTHH:mm:ss)、时区偏移值(K 即 -/+HH:mm)和国家/地区名称,并且想从我的网站中的这些值中获取 IANA 格式的 ZoneId API.
例如:
public static string FetchZoneID(string dateTime, string offset, string countryName)
{
//fetch zoneID
return zoneId;
}
价值
dateTime = "2020-02-06T06:11:01", offset = "+13:00", countryName = "New Zealand"
我应该得到
zoneId = "Pacific/Auckland"
以及值
dateTime = "2020-05-06T06:11:01", offset = "+12:00", countryName = "New Zealand"
我应该得到(由于 DST)
zoneId = "Pacific/Auckland"
目前使用 NodaTime,我能够获取特定国家/地区的所有 zoneId,但无法弄清楚如何根据日期时间和偏移值过滤这些。
var zoneIds = TzdbDateTimeZoneSource.Default.ZoneLocations.Where(x => x.CountryName == countryName)
.Select(x => x.ZoneId);
有人可以帮我解决这个问题吗?
注意:如果多个 zoneId 符合给定偏移量的条件,将使用第一个值。
我将稍微更改您的方法签名,并展示您如何可以列出所有 给定国家/地区的可能时区 ID,其中偏移量与特定本地日期相匹配和时间:
public static ICollection<string> FetchZoneIds(OffsetDateTime dateTime, string countryCode)
{
return TzdbDateTimeZoneSource.Default.ZoneLocations
.Where(x => x.CountryCode == countryCode)
.Select(x => dateTime.InZone(DateTimeZoneProviders.Tzdb[x.ZoneId]))
.Where(x => x.Offset == dateTime.Offset)
.Select(x => x.Zone.Id)
.ToList();
}
这里有一个小测试方法来说明使用字符串输入调用并转储到输出:
private static void Test(string dtoString, string countryCode)
{
Console.WriteLine($"{dtoString} ({countryCode})");
var offsetDateTime = OffsetDateTimePattern.GeneralIso.Parse(dtoString).Value;
var zoneIds = FetchZoneIds(offsetDateTime, countryCode);
foreach (var zoneId in zoneIds)
{
Console.WriteLine(zoneId);
}
Console.WriteLine();
}
您的第一个示例给出了单一的预期结果:
Test("2020-02-06T06:11:01+13:00", "NZ");
2020-02-06T06:11:01+13:00 (NZ)
Pacific/Auckland
你的第二个例子也是:
Test("2020-05-06T06:11:01+12:00", "NZ");
2020-05-06T06:11:01+12:00 (NZ)
Pacific/Auckland
但看看这里发生了什么:
Test("2020-11-01T01:00:00-05:00", "US");
2020-11-01T01:00:00-05:00 (US)
America/New_York
America/Detroit
America/Kentucky/Louisville
America/Kentucky/Monticello
America/Indiana/Indianapolis
America/Indiana/Vincennes
America/Indiana/Winamac
America/Indiana/Marengo
America/Indiana/Petersburg
America/Indiana/Vevay
America/Chicago
America/Indiana/Tell_City
America/Indiana/Knox
America/Menominee
America/North_Dakota/Center
America/North_Dakota/New_Salem
America/North_Dakota/Beulah
重要的是,请注意结果中有东部时间和中部时间的条目,主要是America/New_York
和America/Chicago
。怎么可能?
不,这不是错误。 You can verify it here。在美国,夏令时不是一下子就来的。它从东到西一次走一个时区。因此,当回退过渡发生在东部时区(2:00 EDT 变为 1:00 EST)时,中部时区仍为 1:00 EDT。它不会再过渡一个小时。换句话说,它 1:00 在 EST 和 CDT 中同时具有 UTC-5 偏移量。
如果你不关心这些事情,当然你可以做一个.FirstOrDefault()
(当没有匹配时默认是一个null
字符串)。但你可能确实会遇到像这样的边缘情况。