我使用NodaTime因为其时区信息数据很好的支持,但我有我需要的转换的情况下DateTimeZone
到TimeZoneInfo
在Quartz.NET使用。
这里有什么建议的方法? IANA拥有Windows时区和时区信息时区之间的映射文件,我可以创建可利用这些信息的扩展方法是什么?
谢谢,迪安
我使用NodaTime因为其时区信息数据很好的支持,但我有我需要的转换的情况下DateTimeZone
到TimeZoneInfo
在Quartz.NET使用。
这里有什么建议的方法? IANA拥有Windows时区和时区信息时区之间的映射文件,我可以创建可利用这些信息的扩展方法是什么?
谢谢,迪安
我会尽可能避免使用反射。 我不喜欢赌上你的方法与未来版本的工作:)
随意立案此功能在将来的版本功能请求,但目前我会建立起自己的反向字典更稳定的方式:
// Note: this version lets you work with any IDateTimeZoneSource, although as the only
// other built-in source is BclDateTimeZoneSource, that may be less useful :)
private static IDictionary<string, string> LoadTimeZoneMap(IDateTimeZoneSource source)
{
var nodaToWindowsMap = new Dictionary<string, string>();
foreach (var bclZone in TimeZoneInfo.GetSystemTimeZones())
{
var nodaId = source.MapTimeZoneId(bclZone);
if (nodaId != null)
{
nodaToWindowsMap[nodaId] = bclZone.Id;
}
}
return nodaToWindowsMap;
}
当然,这不会覆盖TZDB的所有时区。 事实上,它甚至不会给我们能够给基于我们使用CLDR信息的所有信息...... CLDR给出了每个Windows ID多个映射,我们只存储此刻的第一个。 我们一直在试图找出如何暴露更多的是,但还没有进行管理。 思考欢迎野田佳彦时间邮件列表上:)
另外请注意,仅仅因为有首创置业和TZDB区之间的映射并不意味着他们会实际上给的一切相同的结果 - 它只是提供的最接近的映射。
啊哈,我发现它- TzdbDateTimeZoneSource
有MapTimeZoneId
,我可以跳进方法TimeZoneInfo.FindSystemTimeZoneById
。
编辑: MapTimeZoneId
确实从Windows时区到时区信息的映射......我最终诉诸反射做相反方向的映射:
using System;
using System.Collections.Generic;
using System.Reflection;
using NodaTime;
using NodaTime.TimeZones;
/// <summary>
/// Extension methods for <see cref="DateTimeZone" />.
/// </summary>
internal static class DateTimeZoneExtensions
{
private static readonly Lazy<IDictionary<string, string>> map = new Lazy<IDictionary<string, string>>(LoadTimeZoneMap, true);
public static TimeZoneInfo ToTimeZoneInfo(this DateTimeZone timeZone)
{
string id;
if (!map.Value.TryGetValue(timeZone.Id, out id))
{
throw new TimeZoneNotFoundException(string.Format("Could not locate time zone with identifier {0}", timeZone.Id));
}
TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(id);
if (timeZoneInfo == null)
{
throw new TimeZoneNotFoundException(string.Format("Could not locate time zone with identifier {0}", timeZone.Id));
}
return timeZoneInfo;
}
private static IDictionary<string, string> LoadTimeZoneMap()
{
TzdbDateTimeZoneSource source = new TzdbDateTimeZoneSource("NodaTime.TimeZones.Tzdb");
FieldInfo field = source.GetType().GetField("windowsIdMap", BindingFlags.Instance | BindingFlags.NonPublic);
IDictionary<string, string> map = (IDictionary<string, string>)field.GetValue(source);
// reverse the mappings
Dictionary<string, string> reverseMap = new Dictionary<string, string>();
foreach (KeyValuePair<string, string> kvp in map)
{
reverseMap.Add(kvp.Value, kvp.Key);
}
return reverseMap;
}
}
您可以使用TimeZoneConverter通过图书馆马特·约翰逊 。
通过NodeTime TzdbZoneLocation使用的是了zoneid IANA时区 ,这样你就可以像这样得到的TimeZoneInfo:
string windowsTimeZoneName = TZConvert.IanaToWindows(tzdbZoneLocation.ZoneId);
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(windowsTimeZoneName);
不要忘了,以防万一某种回退的使用try-catch来包装它。
另外,也要看看原来的马特·约翰逊的解决方案为IANA时区和Windows时区之间的转换。
其中不存在PCL - 然而这一切都不在PCL,因为大部分的工作是由.NET在.GetSystemTImeZones()和.FindSystemTIemZoneById()方法来完成工作。
我目瞪口呆的是,所有的信息,你可以走出NodaTime的,越来越为“EST”的缩写,简单的东西,当你已经拥有“美/东”的区域名称似乎已经停止在我的轨道。