我想通过提供国家/地区代码将特定日期时间值转换为使用NodaTime的UTC。
例如国家是土耳其,国家代码是TR,具体日期时间是“2016年2月5日下午7:45”,它将是“2016年2月5日下午5:45”是否可能?
我的窗户位置也不是土耳其。
提前谢谢你?
答案 0 :(得分:2)
嗯,你不能只用国家代码来做 - 你需要一个时区。在一些国家/地区有多个时区。
如果您将时区设为DateTimeZone
(通过BCL TimeZoneInfo
或来自TZDB时区提供商),您将:
LocalDateTime
,例如使用LocalDateTimePattern
解析文本LocalDateTime.InZoneLeniently
(或类似的 - 稍后会详细介绍)以获取ZonedDateTime
WithZone(DateTimeZone.Utc)
将其转换为基于UTC的ZonedDateTime
关于InZoneLeniently
,InZoneStrictly
或InZone(DateTimeZone, ZoneLocalMappingResolver)
的部分是因为本地日期和时间可能会发生两次或根本不会发生在DST转换周围。有关详细信息,请参阅user guide。
示例代码:
using System;
using NodaTime;
using NodaTime.Text;
class Test
{
static void Main()
{
var text = "Feb 5, 2016 7:45 PM";
var zone = DateTimeZoneProviders.Tzdb["Europe/Istanbul"];
var pattern = LocalDateTimePattern.CreateWithInvariantCulture("MMM d, YYYY h:mm tt");
var local = pattern.Parse(text).Value;
var zoned = local.InZoneStrictly(zone);
var utc = zoned.WithZone(DateTimeZone.Utc);
Console.WriteLine(utc); // 2016-02-05T17:45:00 UTC (+00)
}
}
现在,为了从国家/地区代码中查找时区,TZDB(IANA)数据库附带有关时区位置的信息,这些信息在Noda Time中公开。例如,如果您有一个ISO-3166双字母国家/地区代码,则可以使用:
using NodaTime;
using NodaTime.TimeZones;
using System.Linq;
...
var code = "TR"; // Turkey
var zoneId = TzdbDateTimeZoneSource.Default.ZoneLocations
.Single(loc => loc.CountryCode == code)
.ZoneId;
var zone = DateTimeZoneProviders.Tzdb[zoneId];
如果有多个带有给定国家/地区代码的区域(或无),则Single
来电将失败。
如果您经常查找区域,则可能需要构建字典:
var zonesByCountryCode = TzdbDateTimeZoneSource.Default
.ZoneLocations
.GroupBy(loc => loc.CountryCode)
.Where(g => g.Count() == 1) // Single-zone countries only
.ToDictionary(g => g.Key, g => g.First());