Noda Time IANA将Etc/UTC映射到Windows时区

8

我有一个全球网站,将 IANA 时区 id 传递到服务器,并使用 Noda Time 在 c# 5 web 应用程序中映射到 Windows 时区。

“Etc/UTC” 被传递到服务器,但是 Noda Time 无法将其映射到 Windows 时区。如何映射 IANA 时区 id?

public TimeZoneInfo GetTimeZoneByIanaId(string ianaTimeZoneId)
{
    TzdbDateTimeZoneSource timeZoneSource = TzdbDateTimeZoneSource.Default;
    IList<MapZone> zoneMaps = timeZoneSource.WindowsMapping.MapZones;

    // resolve any link, since the CLDR doesn't necessarily use canonical IDs
    IList<string> mapZoneIds = timeZoneSource.CanonicalIdMap.Where(map => map.Value.Equals(ianaTimeZoneId, StringComparison.OrdinalIgnoreCase)).Select(x => x.Key).ToList();
    MapZone mapZone = zoneMaps.FirstOrDefault(zoneMap => zoneMap.TzdbIds.Any(mapZoneIds.Contains));

    if (mapZone == null)
    {
        throw new TimeZoneNotFoundException("Unable to determine the clients timezone using the jsTimezoneDetect plugin");
    }

    TimeZoneInfo timeZone = TimeZoneInfo.FindSystemTimeZoneById(mapZone.WindowsId);

    if (timeZone == null)
    {
        throw new TimeZoneNotFoundException("Unable to determine the clients timezone from NodaTime");
    }

    return timeZone;
}

看起来 https://code.google.com/p/noda-time/source/browse/data/cldr/windowsZones-25.xml 上没有 CLDR 定义的 UTC 映射。你可能需要硬编码这个 :( - Jon Skeet
好的,谢谢。是的,这是因为该条目在映射中不存在的问题 :( - Jon Skeet
1个回答

7
正如Jon所指出的,CLDR映射中没有"Etc/UTC"。相反,CLDR将Windows的"UTC"时区映射到"Etc/GMT"。以我个人看来,这是错误的。
CLDR需要“稳定的标识符”,因此在时区名称更改时通常不会更新其映射。相反,通常应遵循时区数据库中的“链接”以映射到规范区域。
然而,TZDB并不认为"Etc/GMT""Etc/UTC"的链接。它们是两个不同的区域。还有"Etc/UCT"。这样,依赖TZDB进行时区缩写的应用程序可以使用他们选择的缩写(GMT、UTC或UCT)。(请参见此处的讨论。
无论如何,感谢您提醒我们这个问题。我已经更新了映射函数以考虑这一点。

这是我所知道的唯一一个 - 至少,如果您使用我在另一个答案中链接的映射函数,它会尝试遵循所有tzdb链接。差异是因为CLDR对“规范”的理解与tzdb不同。我已经添加了一些细节,考虑到Noda Time的下一个主要版本。 - Matt Johnson-Pint
太棒了,我有一个全球用户群,而NodeTime已经解决了我在时区偏移方面遇到的很多问题。这是一个非常出色的解决方案,谢谢。 - user3772576

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接