如何在Windows和IANA时区之间进行转换? [英] How to translate between Windows and IANA time zones?
问题描述
如的时区标签维基,有两种不同风格的时区。
As described in the timezone tag wiki, there are two different styles of time zones.
-
对于那些使用Windows和.Net
的TimeZoneInfo
类是由一个值来识别,如东部标准时间<使用Microsoft提供的/ code>。
Those provided by Microsoft for use with Windows and the .Net
TimeZoneInfo
class are identified by a value such asEastern Standard Time
.
这些都是由一个值确定了TZDB提供IANA如美国/纽约
。
Those provided by IANA in the TZDB are identified by a value such as America/New_York
.
很多基于互联网的API使用的IANA时区,但对于众多的原因之一,可能需要将其转换为Windows时区ID,反之亦然。
Many Internet-based APIs use the IANA time zones, but for numerous reasons one might need to convert this to a Windows time zone id, or vice-versa.
如何在.net中可能?
How can this be accomplished in .Net?
推荐答案
有关Windows和IANA时区标识符之间的转换数据的主要来源是的单向code CLDR 。
The primary source of the data for conversion between Windows and IANA time zone identifiers is part of the Unicode CLDR.
在大多数情况下,一个IANA时区可以被映射到一个单一的视窗时区。但相反的是不正确的。一个单一的Windows时区可能映射到多个IANA时区。
In most cases, an IANA time zone can be mapped to a single Windows time zone. But the reverse is not true. A single Windows time zone might be mapped to more than one IANA time zone.
在除了作为一个卓越的日期和时间的API,在野田佳彦时间库包含了CLDR映射的嵌入式副本。
In addition to being a superior date time API, the Noda Time library contains an embedded copy of the CLDR mappings.
下面的功能可以被用来转换:
The following functions can be used to convert:
// This will return the Windows zone that matches the IANA zone, if one exists.
public string IanaToWindows(string ianaZoneId)
{
var utcZones = new[] { "Etc/UTC", "Etc/UCT", "Etc/GMT" };
if (utcZones.Contains(ianaZoneId, StringComparer.Ordinal))
return "UTC";
var tzdbSource = NodaTime.TimeZones.TzdbDateTimeZoneSource.Default;
// resolve any link, since the CLDR doesn't necessarily use canonical IDs
var links = tzdbSource.CanonicalIdMap
.Where(x => x.Value.Equals(ianaZoneId, StringComparison.Ordinal))
.Select(x => x.Key);
// resolve canonical zones, and include original zone as well
var possibleZones = tzdbSource.CanonicalIdMap.ContainsKey(ianaZoneId)
? links.Concat(new[] {tzdbSource.CanonicalIdMap[ianaZoneId], ianaZoneId})
: links;
// map the windows zone
var mappings = tzdbSource.WindowsMapping.MapZones;
var item = mappings.FirstOrDefault(x => x.TzdbIds.Any(possibleZones.Contains));
if (item == null) return null;
return item.WindowsId;
}
// This will return the "primary" IANA zone that matches the given windows zone.
// If the primary zone is a link, it then resolves it to the canonical ID.
public string WindowsToIana(string windowsZoneId)
{
if (windowsZoneId.Equals("UTC", StringComparison.Ordinal))
return "Etc/UTC";
var tzdbSource = NodaTime.TimeZones.TzdbDateTimeZoneSource.Default;
var tzi = TimeZoneInfo.FindSystemTimeZoneById(windowsZoneId);
if (tzi == null) return null;
var tzid = tzdbSource.MapTimeZoneId(tzi);
if (tzid == null) return null;
return tzdbSource.CanonicalIdMap[tzid];
}
请注意,该映射UTC已被另案处理。这是因为CLDR错误地映射UTC到ETC / GMT
和ETC / GMT
未设置起来作为TZDB链接ETC / UTC
。 更多关于此这里。
Note that the mapping for UTC has to be handled separately. This is because the CLDR erroneously maps UTC to "Etc/GMT"
, and "Etc/GMT"
is not set up as a link to "Etc/UTC"
in the tzdb. More on this here.
这篇关于如何在Windows和IANA时区之间进行转换?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!