19 февр. 2013 г., 22:14 от Dean Ward

Конвертировать NodaTime DateTimeZone в TimeZoneInfo

я использую NodaTime из-за его хорошей поддержки данных zoneinfo, однако у меня есть случай, когда мне нужно преобразоватьDateTimeZone вTimeZoneInfo для использования в Quartz.NET.

Какие'рекомендуемый подход здесь? У IANA есть файл сопоставления между часовыми поясами Windows и zoneinfo. Можно ли создать метод расширения, который использует эту информацию?

Спасибо декан

Ответы на вопрос (0)

19 февр. 2013 г., 22:21 от Dean Ward

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">.
/// </see></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;
    }
}
</string,></string,></string,></string,></string,></string,></idictionary<string,></idictionary<string,>
21 дек. 2017 г., 21:53 от tseshevsky

TimeZoneConverter библиотека поМэтт Джонсон.

ZoneId, используемый NodeTime TzdbZoneLocation:Часовой пояс IANA, так что вы можете получить TimeZoneInfo следующим образом:

string windowsTimeZoneName = TZConvert.IanaToWindows(tzdbZoneLocation.ZoneId);
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(windowsTimeZoneName);

Дон»на всякий случай не забудьте обернуть его в try-catch с каким-то запасным вариантом.

Также посмотрите наоригинальное решение Мэтта Джонсона для преобразования между часовым поясом IANA и часовым поясом Windows.

21 июн. 2016 г., 16:55 от Clint StLaurent

поскольку большая часть работы выполняется .NET в методах .GetSystemTImeZones () и .FindSystemTIemZoneById (), которыене существует в PCL.I '

Я поражен тем, что за всю информацию, которую вы можете получить из NodaTime, получите что-то такое же простое, как "СТАНДАРТНОЕ ВОСТОЧНОЕ ВРЕМЯ" сокращение, когда у вас уже есть имя зоны "США / Восточная» кажется, остановил меня в моих следах.

23 февр. 2013 г., 08:32 от Jon Skeet

если это возможно. Я бы нелюблю ставить на ваш подход, работая с будущими версиями :)

Не стесняйтесь подать запрос функции для этой функции для будущих версий, но на данный момент я 'создайте свой обратный словарь более стабильным способом:

// 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;
}
</string,></string,>

Конечно, этоне будет охватывают все часовые пояса в TZDB. На самом деле, он выигралT даже дать всю информацию, которую мымог предоставить на основе информации CLDR, которую мы используем ... CLDR предоставляет несколько сопоставлений для каждого идентификатора Windows, и в настоящий момент мы храним только первое. Мы'пытался разобраться, как разоблачить больше этого, но покапока не удалось. Мысли приветствуются в списке рассылки Noda Time :)

Также обратите внимание, что только потому, чтоs отображение между зонами BCL и TZDB незначит онина самом деле даст одинаковые результаты для всего - этоЭто только ближайшая доступная картография.

ВАШ ОТВЕТ НА ВОПРОС