Переход на летнее время с абсолютной датой

Я пытаюсь реализовать правильную обработку корректировки DST в моем приложении будильника. Итак, я читаю описание для DYNAMIC_TIME_ZONE_INFORMATION который я использую, чтобы получить информацию о текущей настройке DST через GetTimeZoneInformationForYear API, и это говорит следующее:

DaylightDate:

СИСТЕМНОЕ ВРЕМЯ структура, которая содержит дату и местный
время перехода с стандартного на летнее время
происходит в этой операционной системе. Если часовой пояс не поддерживает
летнее время или если вызывающему абоненту необходимо отключить летнее время
время wMonth член в структуре SYSTEMTIME должен быть нулевым. Если
эта дата указана, член StandardDate в этой структуре должен
Также будет указано. В противном случае система предполагает, что данные часового пояса
недействителен и никакие изменения не будут применены. Чтобы выбрать правильный день в
месяц, установите wYear член к нулю, wHour а также wMinute члены
время перехода, wDayOfWeek член соответствующего
будний день, а WDAY член, чтобы указать на возникновение дня
неделя в течение месяца (от 1 до 5, где 5 означает окончательный
появление в течение месяца, если этот день недели не произошел 5
раз).

Если wYear член не ноль, дата перехода
абсолютный; это произойдет только один раз. В противном случае это относительный
дата, которая происходит ежегодно.

Я также проверяю текущие корректировки DST наблюдаются во всем мире, и если относительные корректировки DST кажутся довольно простыми, я не совсем уверен, как следующие корректировки могут быть переданы через DYNAMIC_TIME_ZONE_INFORMATION — с абсолютным месяцем и днем.

Например:

Egypt
-----
DST Start: May 15
DST End: Last Friday September

или этот:

Iran
----
DST Start: March 21–22
DST End: September 21–22

Кто-нибудь знает как это сделать?

0

Решение

Чтобы понять структуру часового пояса, полезно взглянуть на реестр Windows под следующим ключом:

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\

Здесь вы найдете все встроенные часовые пояса база данных часовых поясов Microsoft, который поддерживается Microsoft через Windows Updates.

Давайте рассмотрим один из приведенных вами примеров:

.\Egypt Standard Time\

Египет

.\Egypt Standard Time\Dynamic DST\

Египет Динамический DST

Отсюда видно, что существуют определенные правила перехода на летнее время, определенные на 2005-2011 годы. За пределами этого диапазона мы возвращаемся к TZI значение корневой записи.

Вы заметите, что там отсутствует запись 2014 года для Египта. Это потому, что Египет почти не уведомил о предстоящее изменение. Вы можете ожидать, что скоро будет доступно исправление от Microsoft, доступное с обновлением.

Двоичные данные в реестре десериализуются в REG_TZI_FORMAT структура, которая выглядит так:

typedef struct _REG_TZI_FORMAT
{
LONG Bias;
LONG StandardBias;
LONG DaylightBias;
SYSTEMTIME StandardDate;
SYSTEMTIME DaylightDate;
} REG_TZI_FORMAT;

Проблема, о которой вы должны знать, заключается в том, что Windows не любит часовые пояса, которые переходят прямо в полночь. Обходной путь заключается в том, что вместо «00:00 в последнюю пятницу сентября» вы должны сказать «23: 59: 59,999 в последнюю Четверг в сентябре «. Однако, здесь вы должны быть осторожны, потому что подобные правила могут иногда приводить к ошибочным производным датам. Чтобы противостоять этому, иногда каждый год будет иметь свое собственное правило. Формат шаблона повторения все еще используется, а не фиксированный формат даты, в основном для согласованности.

Однако есть еще одна проблема — эта структура может поддерживать только два перехода на летнее время в год. Один на DaylightDate когда начинается летнее время, и один на StandardDate когда заканчивается летнее время. С тех пор как Египет принимает DST кроме Рамадана, будут четыре перехода. Это также произошло в Египет в 2010 году, а также регулярно происходит в Марокко. Чтобы справиться с этим недостатком дизайна, Microsoft традиционно выпустила множественный обновления, приуроченные к изменениям. (Например, см. KB2297272.)

Я предполагаю, что Microsoft вытолкнет изменения с многократным обновлением, поэтому в качестве примера мы пропустим период Рамадана. Это правило начинается в летнее время во 2-ю среду мая в 23: 59: 59,999 и заканчивается в последний четверг сентября в 23: 59: 59,999.

"TZI" = 88ffffff 00000000 c4ffffff 000009000400050017003b003b00e703 000005000300020017003b003b00e703

Это соответствует REG_TZI_FORMAT структура, имеющая эти значения (как JSON для ясности):

{
"Bias" : -120,         // Standard offset is UTC+2
"StandardBias" : 0,
"DaylightBias" : -60,  // Subtract an hour for DST
"StandardDate" : {
"wYear" : 0,       // Recurrence pattern
"wMonth" : 9,      // September
"wDayOfWeek" : 4,  // Thursday
"wDay" : 5,        // Last occurrence
"wHour" : 23,
"wMinute" : 59,
"wSecond" : 59,
"wMilliseconds" : 999
},
"DaylightDate" : {
"wYear" : 0,       // Recurrence pattern
"wMonth" : 5,      // May
"wDayOfWeek" : 3,  // Wednesday
"wDay" : 2,        // Second occurrence
"wHour" : 23,
"wMinute" : 59,
"wSecond" : 59,
"wMilliseconds" : 999
}
}

Я думаю, что этот ответ достаточно длинный, поэтому я предоставлю вам возможность экстраполировать правила для Ирана, если хотите. Тем не менее, я укажу, что данные Windows по Ирану были неверными с 2009 года и до сих пор не получили обновления. : — /

В качестве примечания: если вы хотите указать правило с фиксированной датой, вы можете указать ненулевое значение «реального» года. Тогда поле дня представляет фактический день, а не происшествие. Однако этого обычно избегают, поскольку это имеет смысл только для правил динамического перехода на летнее время, которые применяются к отдельным годам. Не имеет смысла использовать фиксированную дату в общем TZI запись в корневом узле.

ОБНОВИТЬ

Microsoft выпустила обновление для Египта на 2014 год в KB2967990.

3

Другие решения

Иран странен тем, что даты перехода на летнее время не соответствуют нормальным правилам, которые ожидает реестр Microsoft. Например: 2-е воскресенье марта. Поэтому я согласен, что вам нужно использовать абсолютные даты, но это достигается с помощью формата реестра. Дни перехода на летнее время меняются почти каждый год.

Даты перехода на летнее время в Иране основаны на персидском календаре
https://mm.icann.org/pipermail/tz/2003-March/012053.html

Таким образом, метод динамического реестра будет ответом с большим количеством изменений каждый год!

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector