我正在使用NodaTime,因为它对zoneinfo数据有很好的支持,但我有一个案例需要将其DateTimeZone转换TimeZoneInfo为在Quartz.NET中使用.
这里推荐的方法是什么?IANA在Windows时区和zoneinfo时区之间有一个映射文件,我可以创建一个利用此信息的扩展方法吗?
谢谢,迪恩
Jon*_*eet 11
如果可能的话,我会避免使用反射.我不想打赌你使用未来版本的方法:)
请为将来的版本提供此功能的功能请求,但目前我将以更稳定的方式构建您的反向字典:
// 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;
}
Run Code Online (Sandbox Code Playgroud)
当然,这不会涵盖TZDB中的所有时区.事实上,它甚至不会根据我们使用的CLDR信息提供我们可以提供的所有信息...... CLDR为每个Windows ID提供多个映射,我们目前只存储第一个.我们一直试图弄清楚如何揭露更多,但尚未管理.在Noda Time邮件列表上欢迎思考:)
另请注意,仅仅因为BCL和TZDB区域之间存在映射并不意味着它们实际上会为所有内容提供相同的结果 - 它只是最接近的可用映射.
啊哈,我找到了 -TzdbDateTimeZoneSource有一个MapTimeZoneId我可以插入的方法TimeZoneInfo.FindSystemTimeZoneById。
编辑:MapTimeZoneId是否从 Windows 时区映射到 zoneinfo...我最终求助于反射来进行相反方向的映射:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4093 次 |
| 最近记录: |