Squeak.ru - шаблоны программирования

Преобразование часового пояса в стиле posix в timezoneinfo в С# .net

Я получаю информацию о часовом поясе с другой машины в формате:

"CET-1CEST,M3.5.0/2,M10.5.0/3"

(Часовые пояса в стиле Posix)

Мне нужно разобрать это и преобразовать в c# .net TimeZoneInfo class.

Есть ли способ добиться этого?

29.10.2014

Ответы:


1

Согласно этой статье: http://www.ibm.com/developerworks/aix/library/au-aix-posix/ время POSIX, например "CST6CDT,M3.2.0/2:00:00,M11.1.0/2:00:00", имеет следующие характеристики:

  • CST6CDT — это название часового пояса.
  • CST — это аббревиатура, используемая, когда летнее время отключено.
  • 6 часов - это разница во времени с GMT
  • CDT — это аббревиатура, используемая при переходе на летнее время.
  • ,M3 - третий месяц
  • .2 - второе появление дня в месяце
  • .0 это воскресенье
  • /2:00:00 время
  • ,M11 - одиннадцатый месяц
  • .1 - первое появление дня в месяце
  • .0 это воскресенье
  • /2:00:00 время

и дата в формате Mm.n.d, где:

  • Мм (1-12) на 12 месяцев
  • n (1-5) 1 для первой недели и 5 для последней недели месяца
  • d (0-6) 0 для воскресенья и 6 для субботы

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

public static TimeZoneInfo ConvertPosixToTimeZoneInfo(string posix)
    {
        string[] tokens = posix.Split(',');
        tokens[0] = tokens[0].Replace("/", ".");
        var match = Regex.Match(tokens[0], @"[-+]?[0-9]*\.?[0-9]+").Value;
        var ticks = (long)(decimal.Parse(match, CultureInfo.InvariantCulture) * 60) * 600000000;
        var baseOffset = new TimeSpan(ticks);

        var systemTimeZones = TimeZoneInfo.GetSystemTimeZones().Where(t => t.BaseUtcOffset == baseOffset).ToList();

        var startRuleTokens = tokens[1].TrimStart('M').Split('/');
        var startDateRuleTokens = startRuleTokens[0].Split('.');
        var startTimeRuleTokens = startRuleTokens[1].Split(':');

        var endRuleTokens = tokens[2].TrimStart('M').Split('/');
        var endDateRuleTokens = endRuleTokens[0].Split('.');
        var endTimeRuleTokens = endRuleTokens[1].Split(':');

        int? targetIndex = null;
        for (int i = 0; i < systemTimeZones.Count; i++)
        {
            var adjustmentRules = systemTimeZones[i].GetAdjustmentRules();
            foreach (var rule in adjustmentRules)
            {
                if (rule.DaylightTransitionStart.Month == int.Parse(startDateRuleTokens[0]) &&
                    rule.DaylightTransitionStart.Week == int.Parse(startDateRuleTokens[1]) &&
                    rule.DaylightTransitionStart.DayOfWeek == (DayOfWeek)int.Parse(startDateRuleTokens[2]) &&
                    rule.DaylightTransitionStart.TimeOfDay.Hour == int.Parse(startTimeRuleTokens[0]) &&
                    rule.DaylightTransitionStart.TimeOfDay.Minute == int.Parse(startTimeRuleTokens[1]) &&
                    rule.DaylightTransitionStart.TimeOfDay.Second == int.Parse(startTimeRuleTokens[2]) &&

                    rule.DaylightTransitionEnd.Month == int.Parse(endDateRuleTokens[0]) &&
                    rule.DaylightTransitionEnd.Week == int.Parse(endDateRuleTokens[1]) &&
                    rule.DaylightTransitionEnd.DayOfWeek == (DayOfWeek)int.Parse(endDateRuleTokens[2]) &&
                    rule.DaylightTransitionEnd.TimeOfDay.Hour == int.Parse(endTimeRuleTokens[0]) &&
                    rule.DaylightTransitionEnd.TimeOfDay.Minute == int.Parse(endTimeRuleTokens[1]) &&
                    rule.DaylightTransitionEnd.TimeOfDay.Second == int.Parse(endTimeRuleTokens[2]))
                {
                    targetIndex = i;
                    break;
                }
            }
        }

        if (targetIndex.HasValue)
            return systemTimeZones[targetIndex.Value];
        return null;
    }
27.10.2016

2

Я бы разобрал его в соответствии с его форматом: http://www.ibm.com/developerworks/aix/library/au-aix-posix/

Возможно, вы могли бы также рассмотреть: http://nodatime.org/ - в настоящее время я не знаю, поддерживают ли они это.

29.10.2014
  • После того, как вы проанализировали POSIX, чтобы получить standard.Offset, daylight.Offset, toDaylight.Date и toStandard.Date, вам нужно выполнить итерацию по доступным TimeZoneInfo, чтобы найти совпадение. Если совпадения нет, повторите еще раз, игнорируя две даты. Если вы получаете несколько совпадений, вам нужно будет выбрать одно. Если совпадений нет, то, вероятно, это строка здравого смысла, а не строка POSIX. :) 20.02.2015

  • 3

    Следующий код должен помочь.

    Имейте в виду, что хотя это и даст вам действительный объект TimeZoneInfo, он не сопоставляет информацию с существующими часовыми поясами Windows. Вы можете использовать различные функции преобразования, такие как TimeZoneInfo.ConvertTime, но не ожидайте, что он волшебным образом узнает, что PST8PDT должно быть выровнено с "Pacific Standard Time".

    public static TimeZoneInfo PosixToTzi(string posixTz)
    {
        var parts = posixTz.Split(',');
        var zoneparts = Regex.Split(parts[0], @"([0-9\+\-\.]+)");
    
        double baseOffsetHours;
        if (zoneparts.Length > 1)
        {
            if (!Double.TryParse(zoneparts[1], out baseOffsetHours))
                throw new FormatException();
        }
        else
        {
            // recognize RFC822 time zone abbreviations
            switch (zoneparts[0].ToUpper())
            {
                case "UT":
                case "UTC":
                case "GMT":
                    baseOffsetHours = 0;
                    break;
                case "EDT":
                    baseOffsetHours = 4;
                    break;
                case "EST":
                case "CDT":
                    baseOffsetHours = 5;
                    break;
                case "CST":
                case "MDT":
                    baseOffsetHours = 6;
                    break;
                case "MST":
                case "PDT":
                    baseOffsetHours = 7;
                    break;
                case "PST":
                    baseOffsetHours = 8;
                    break;
                default:
                    throw new FormatException();
            }
        }
    
        double dstOffsetHours = baseOffsetHours - 1;
        if (zoneparts.Length == 4)
        {
            if (!Double.TryParse(zoneparts[3], out dstOffsetHours))
                throw new FormatException();
        }
    
        var baseOffset = TimeSpan.FromHours(-baseOffsetHours);
        var dstDelta = TimeSpan.FromHours(baseOffsetHours - dstOffsetHours);
    
        var rules = new List<TimeZoneInfo.AdjustmentRule>();
        if (parts.Length == 3)
        {
            var rule = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(
                DateTime.MinValue.Date, DateTime.MaxValue.Date, dstDelta,
                ParsePosixTransition(parts[1]), ParsePosixTransition(parts[2]));
    
            rules.Add(rule);
        }
    
        return TimeZoneInfo.CreateCustomTimeZone(posixTz, baseOffset, parts[0], zoneparts[0],
            zoneparts[zoneparts.Length == 3 ? 2 : 0], rules.ToArray());
    }
    
    private static TimeZoneInfo.TransitionTime ParsePosixTransition(string transition)
    {
        var parts = transition.Split('/');
        if (parts.Length > 2)
                throw new FormatException();
    
        double hours = 0;
        if (parts.Length == 2)
        {
            if (!Double.TryParse(parts[1], out hours))
                throw new FormatException();
        }
        var time = DateTime.MinValue.AddHours(hours);
    
        if (transition.StartsWith("M", StringComparison.OrdinalIgnoreCase))
        {
            var dateParts = parts[0].Substring(1).Split('.');
            if (dateParts.Length > 3)
                throw new FormatException();
    
            int month;
            if (!Int32.TryParse(dateParts[0], out month))
                throw new FormatException();
    
            int week;
            if (!Int32.TryParse(dateParts[1], out week))
                throw new FormatException();
    
            int dow;
            if (!Int32.TryParse(dateParts[2], out dow))
                throw new FormatException();
    
            return TimeZoneInfo.TransitionTime.CreateFloatingDateRule(time, month, week, (DayOfWeek) dow);
        }
    
        if (transition.StartsWith("J", StringComparison.OrdinalIgnoreCase))
        {
            int dayNum;
            if (!Int32.TryParse(parts[0].Substring(1), out dayNum))
                throw new FormatException();
            var date = DateTime.MinValue.AddDays(dayNum);
    
            return TimeZoneInfo.TransitionTime.CreateFixedDateRule(time, date.Month, date.Day);
        }
    
        throw new FormatException();
    }
    
    27.04.2015
    Новые материалы

    Угловая структура архитектуры
    Обратите внимание, что эта статья устарела, я решил создать новую с лучшей структурой и с учетом автономных компонентов: https://medium.com/@marekpanti/angular-standalone-architecture-b645edd0d54a..

    «Данные, которые большинство людей используют для обучения своих моделей искусственного интеллекта, поставляются со встроенным…
    Первоначально опубликовано HalkTalks: https://hacktown.com.br/blog/blog/os-dados-que-a-maioria-das-pessoas-usa-para-treinar-seus-modelos-de-inteligencia-artificial- ja-vem-com-um-vies-embutido/..

    Сильный ИИ против слабого ИИ: различия парадигм искусственного интеллекта
    В последние годы изучению и развитию искусственного интеллекта (ИИ) уделяется большое внимание и прогресс. Сильный ИИ и Слабый ИИ — две основные парадигмы в области искусственного интеллекта...

    Правильный способ добавить Firebase в ваш проект React с помощью React Hooks
    React + Firebase - это мощная комбинация для быстрого и безопасного создания приложений, от проверки концепции до массового производства. Раньше (знаете, несколько месяцев назад) добавление..

    Создайте API с помощью Python FastAPI
    Создание API с помощью Python становится очень простым при использовании пакета FastAPI. После установки и импорта вы можете создать приложение FastAPI и указать несколько конечных точек. Каждой..

    Веселье с прокси-сервером JavaScript
    Прокси-серверы JavaScript — это чистый сахар, если вы хотите создать некоторую общую логику в своих приложениях, чтобы облегчить себе жизнь. Вот один пример: Связь клиент-сервер Мы..

    Получить бесплатный хостинг для разработчиков | Разместите свой сайт за несколько шагов 🔥
    Статические веб-сайты — это веб-страницы с фиксированным содержанием и его постоянным содержанием. Но теперь статические сайты также обрабатывают динамические данные с помощью API и запросов...