【问题标题】:Get ZoneId using country name, datetime and timezone offset values in c#在c#中使用国家名称、日期时间和时区偏移值获取ZoneId
【发布时间】:2020-04-01 06:52:10
【问题描述】:

我有日期时间(yyyy-MM-ddTHH:mm:ss)、时区偏移值(K 即 -/+HH:mm)和国家名称,并希望在我的 Web API 中从这些值中获取 IANA 格式的 ZoneId。

例如:

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 符合给定偏移量的条件,将使用第一个值。

【问题讨论】:

  • 为什么?可能有 10 个城市具有相同的偏移量,那么您为什么认为应该选择布里斯班?
  • 我不介意为给定的输入获取多个 zoneId
  • 我的意思是它不是唯一的。 ZoneLocation 值未内置到网络库中,应用程序必须设置参数。
  • 更新了我的示例以避免混淆
  • 请注意,America/DetroitAmerica/New_York 几乎总是具有相同的偏移量,但它们是同一国家/地区的两个不同时区。你想得到哪一个?另一个例子是Asia/ShanghaiAsia/Hong_Kong

标签: c# datetime asp.net-core timezone nodatime


【解决方案1】:

我将稍微更改您的方法签名,并展示如何为给定的国家/地区列出所有可能的时区 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_YorkAmerica/Chicago。怎么可能?

不,这不是错误。 You can verify it here。在美国,夏令时不会一下子发生。它从东到西一次经过一个时区。因此,当在东部时区(美国东部时间 2:00 变为美国东部时间 1:00)发生回退转换时,中部时区仍为美国东部时间 1:00。它不会再过一个小时过渡。换句话说,它是 1:00,同时在 EST 和 CDT 中具有 UTC-5 偏移

如果你不关心这些事情,当然你可以做一个.FirstOrDefault()(当没有匹配时默认是null字符串)。但你可能确实会遇到像这样的极端情况。

【讨论】:

  • 我理解您对边缘情况的担忧,这是我们对应用程序的书面限制,可以使用。
猜你喜欢
  • 2021-06-12
  • 2013-01-13
  • 2012-08-25
  • 2018-03-15
  • 1970-01-01
  • 2017-08-30
  • 1970-01-01
  • 2020-12-28
  • 1970-01-01
相关资源
最近更新 更多