Про заблуждения написано отдельно Изменения часовых поясов в России. Год 2014. Факты.
Теперь про обновление KB2998527.
В чём его технический смысл? Давайте посмотрим на примере одного часового пояса Russian Standard Time.
Вот запись в реестре до установки обновления:
А вот после:
Как видите было UTC+4, стало UTC+3. Но время при этом у нас на компьютере отображается то же самое, что и до установки обновления – скачка нет. К тому же в 2 часа 26 октября должен произойти автоматический перевод часов на один час назад.
Как же всё это сделано? Есть единственный механизм в ОС, который может сделать автоматический перевод времени – это перевод времени «зима-лето». Этот механизм работал на наших компьютерах многие годы.
С технической точки зрения обновление KB2998527 переводит время на час назад в соответствии с новым часовым поясом и одновременно включает переход на летнее время, переводя время на час вперед; кроме этого устанавливает автоматический переход на зимнее время в 2 часа 26 октября на один час назад.
Не верите? Давайте посмотрим. Возьмём три времени в UTC: 10 января 5 часов утра, 10 июня 5 часов утра и 29 ноября 5 часов утра – и посмотрим за разные годы локальное время.
До установки обновления:
year a b c
—- — — —
2009 1/10/2009 9:00:00 AM 6/10/2009 10:00:00 AM 11/29/2009 9:00:00 AM
2010 1/10/2010 9:00:00 AM 6/10/2010 10:00:00 AM 11/29/2010 9:00:00 AM
2011 1/10/2011 9:00:00 AM 6/10/2011 10:00:00 AM 11/29/2011 10:00:00 AM
2012 1/10/2012 9:00:00 AM 6/10/2012 9:00:00 AM 11/29/2012 9:00:00 AM
2013 1/10/2013 9:00:00 AM 6/10/2013 9:00:00 AM 11/29/2013 9:00:00 AM
2014 1/10/2014 9:00:00 AM 6/10/2014 9:00:00 AM 11/29/2014 9:00:00 AM
2015 1/10/2015 9:00:00 AM 6/10/2015 9:00:00 AM 11/29/2015 9:00:00 AM
2016 1/10/2016 9:00:00 AM 6/10/2016 9:00:00 AM 11/29/2016 9:00:00 AM
Теперь посмотрим результат после установки обновления:
year a b c
—- — — —
2009 1/10/2009 8:00:00 AM 6/10/2009 9:00:00 AM 11/29/2009 8:00:00 AM
2010 1/10/2010 8:00:00 AM 6/10/2010 9:00:00 AM 11/29/2010 8:00:00 AM
2011 1/10/2011 8:00:00 AM 6/10/2011 9:00:00 AM 11/29/2011 9:00:00 AM
2012 1/10/2012 8:00:00 AM 6/10/2012 8:00:00 AM 11/29/2012 8:00:00 AM
2013 1/10/2013 8:00:00 AM 6/10/2013 8:00:00 AM 11/29/2013 8:00:00 AM
2014 1/10/2014 9:00:00 AM 6/10/2014 9:00:00 AM 11/29/2014 8:00:00 AM
2015 1/10/2015 8:00:00 AM 6/10/2015 8:00:00 AM 11/29/2015 8:00:00 AM
2016 1/10/2016 8:00:00 AM 6/10/2016 8:00:00 AM 11/29/2016 8:00:00 AM
Обратите внимание: после установки обновления в предыдущие годы время стало меньше на один час, как и положено: теперь у нас UTC+3, а не UTC+4. (Тут как раз кроется засада для программ, которые работают с событиями, привязанными к локальному времени). А вот для нынешнего 2014-го года смешение осталось прежним – UTC+4. Откуда взялся один час пока не ясно, поэтому продолжаем анализ.
Для начала опять посмотрим реестр.
До установки обновления:
После установки обновления:
На скриншотах видно, что каждому году соответствует своя запись, и что после установки обновления число корректировочных записей увеличилось.
Давайте расшифруем эти записи с помощью Powershell.
До установки обновления:
PS C:\Users\1> $a=[system.timezoneinfo]::FindSystemTimeZoneById(«Russian Standard Time»)
PS C:\Users\1> $a | fl *
Id : Russian Standard Time
DisplayName : (UTC+04:00) Moscow, St. Petersbur
StandardName : Russian Standard Time
DaylightName : Russian Daylight Time
BaseUtcOffset : 04:00:00
SupportsDaylightSavingTime : True
PS C:\Users\1> $a.GetAdjustmentRules()
DateStart : 1/1/0001 12:00:00 AM
DateEnd : 12/31/2010 12:00:00 AM
DaylightDelta : 01:00:00
DaylightTransitionStart : System.TimeZoneInfo+TransitionTime
DaylightTransitionEnd : System.TimeZoneInfo+TransitionTime
DateStart : 1/1/2011 12:00:00 AM
DateEnd : 12/31/2011 12:00:00 AM
DaylightDelta : 01:00:00
DaylightTransitionStart : System.TimeZoneInfo+TransitionTime
DaylightTransitionEnd : System.TimeZoneInfo+TransitionTime
Последние два значения не видно, поэтому
Полная расшифровка:
Monday, January 1, 0001 12:00:00 AM
Friday, December 31, 2010 12:00:00 AM
01:00:00
TimeOfDay : 1/1/0001 2:00:00 AM
Month : 3
Week : 5
Day : 1
DayOfWeek : Sunday
IsFixedDateRule : False
TimeOfDay : 1/1/0001 3:00:00 AM
Month : 10
Week : 5
Day : 1
DayOfWeek : Sunday
IsFixedDateRule : False
————————————
Saturday, January 1, 2011 12:00:00 AM
Saturday, December 31, 2011 12:00:00 AM
01:00:00
TimeOfDay : 1/1/0001 2:00:00 AM
Month : 3
Week : 5
Day : 1
DayOfWeek : Sunday
IsFixedDateRule : False
TimeOfDay : 1/1/0001 12:00:00 AM
Month : 1
Week : 1
Day : 1
DayOfWeek : Saturday
IsFixedDateRule : False
После установки обновления:
$a=[system.timezoneinfo]::FindSystemTimeZoneById(«Russian Standard Time»)
$a | fl *
Id : Russian Standard Time
DisplayName : (UTC+03:00) Moscow, St. Petersburg, Volgograd (RTZ 2)
StandardName : Russia TZ 2 Standard Time
DaylightName : Russia TZ 2 Daylight Time
BaseUtcOffset : 03:00:00
SupportsDaylightSavingTime : True
PS C:\Users\1> $a.GetAdjustmentRules()
DateStart : 1/1/0001 12:00:00 AM
DateEnd : 12/31/2010 12:00:00 AM
DaylightDelta : 01:00:00
DaylightTransitionStart : System.TimeZoneInfo+TransitionTime
DaylightTransitionEnd : System.TimeZoneInfo+TransitionTime
DateStart : 1/1/2011 12:00:00 AM
DateEnd : 12/31/2011 12:00:00 AM
DaylightDelta : 01:00:00
DaylightTransitionStart : System.TimeZoneInfo+TransitionTime
DaylightTransitionEnd : System.TimeZoneInfo+TransitionTime
DateStart : 1/1/2014 12:00:00 AM
DateEnd : 12/31/2014 12:00:00 AM
DaylightDelta : 01:00:00
DaylightTransitionStart : System.TimeZoneInfo+TransitionTime
DaylightTransitionEnd : System.TimeZoneInfo+TransitionTime
Полная расшифровка:
Monday, January 1, 0001 12:00:00 AM
Friday, December 31, 2010 12:00:00 AM
01:00:00
TimeOfDay : 1/1/0001 2:00:00 AM
Month : 3
Week : 5
Day : 1
DayOfWeek : Sunday
IsFixedDateRule : False
TimeOfDay : 1/1/0001 3:00:00 AM
Month : 10
Week : 5
Day : 1
DayOfWeek : Sunday
IsFixedDateRule : False
————————————
Saturday, January 1, 2011 12:00:00 AM
Saturday, December 31, 2011 12:00:00 AM
01:00:00
TimeOfDay : 1/1/0001 2:00:00 AM
Month : 3
Week : 5
Day : 1
DayOfWeek : Sunday
IsFixedDateRule : False
TimeOfDay : 1/1/0001 12:00:00 AM
Month : 1
Week : 1
Day : 1
DayOfWeek : Saturday
IsFixedDateRule : False
————————————
Wednesday, January 1, 2014 12:00:00 AM
Wednesday, December 31, 2014 12:00:00 AM
01:00:00
TimeOfDay : 1/1/0001 12:00:00 AM
Month : 1
Week : 1
Day : 1
DayOfWeek : Wednesday
IsFixedDateRule : False
TimeOfDay : 1/1/0001 2:00:00 AM
Month : 10
Week : 5
Day : 1
DayOfWeek : Sunday
IsFixedDateRule : False
Обратите внимание на последние две записи: первая означает включение летнего времени с начала 2014 года, а вторая переход на зимнее время в 2 часа в последнее воскресение октября – ныне это 26 октября.
Вот собственно и всё по технике перевода времени.
Если ещё раз посмотреть на исходные таблицы с контрольными точками времени (до установки обновления), то можно увидеть «скачок» времени на границе года (тут даты не на границе года, но суть отражают правильно):
2011 1/10/2011 9:00:00 AM 6/10/2011 10:00:00 AM 11/29/2011 10:00:00 AM
2012 1/10/2012 9:00:00 AM 6/10/2012 9:00:00 AM 11/29/2012 9:00:00 AM
Понятно, что реально в тот момент время не менялось. Откуда скачок? Это эффект изменения часовых поясов: тогда тоже не просто отменили переход на летнее время – изменился часовой пояс.
Сейчас мы наблюдаем похожий «скачок» времени при переходе с 2013 года на 2014 за счёт изменения часового пояса:
2013 1/10/2013 8:00:00 AM 6/10/2013 8:00:00 AM 11/29/2013 8:00:00 AM
2014 1/10/2014 9:00:00 AM 6/10/2014 9:00:00 AM 11/29/2014 8:00:00 AM
2015 1/10/2015 8:00:00 AM 6/10/2015 8:00:00 AM 11/29/2015 8:00:00 AM
2016 1/10/2016 8:00:00 AM 6/10/2016 8:00:00 AM 11/29/2016 8:00:00 AM
Останется ли в будущем этот «скачок» в таблице? По всей видимости да. Какие последствия? Некоторые программы эту ситуацию не смогут обработать правильно: либо выдадут неправильный результат, либо завершатся аварийно. Неприятность нынешней ситуации в том, что если в прошлый раз один час на границе года «пропадал», то сейчас «появился» один фиктивный локальный час. Понятно, что это просто математический фокус. Программа отработает правильно, если для каждой даты будет учитывать часовой пояс на каждый момент времени. Делают ли это программы? Думаю, что большинство этого не делает, и в большинстве случаев это не нужно, но там, где это критично… в общем передавайте привет депутатам!
На этом всё. Надеюсь, что ваш мозг выдержал путешествия во времени J
PS: кто поставит на то, что будет ещё одно обновление в следующем году, которое «отполирует» текущее обновление?
PSS: код расшифровки
$a=[system.timezoneinfo]::FindSystemTimeZoneById(«Russian Standard Time»)
$a.GetAdjustmentRules()
$b=$a.GetAdjustmentRules()
$b | % {
$_.DateStart
$_.DateEnd
$_.DaylightDelta.ToString()
$_.DaylightTransitionStart
$_.DaylightTransitionEnd
«————————————»
}
Вывод контрольных точек:
$UtcTime2009 = Get-Date -Date «2009-01-10 5:00:00Z»
$UtcTime2010 = Get-Date -Date «2010-01-10 5:00:00Z»
$UtcTime2011 = Get-Date -Date «2011-01-10 5:00:00Z»
$UtcTime2012 = Get-Date -Date «2012-01-10 5:00:00Z»
$UtcTime2013 = Get-Date -Date «2013-01-10 5:00:00Z»
$UtcTime2014 = Get-Date -Date «2014-01-10 5:00:00Z»
$UtcTime2015 = Get-Date -Date «2015-01-10 5:00:00Z»
$UtcTime2016 = Get-Date -Date «2016-01-10 5:00:00Z»
$UtcTime2009b = Get-Date -Date «2009-06-10 5:00:00Z»
$UtcTime2010b = Get-Date -Date «2010-06-10 5:00:00Z»
$UtcTime2011b = Get-Date -Date «2011-06-10 5:00:00Z»
$UtcTime2012b = Get-Date -Date «2012-06-10 5:00:00Z»
$UtcTime2013b = Get-Date -Date «2013-06-10 5:00:00Z»
$UtcTime2014b = Get-Date -Date «2014-06-10 5:00:00Z»
$UtcTime2015b = Get-Date -Date «2015-06-10 5:00:00Z»
$UtcTime2016b = Get-Date -Date «2016-06-10 5:00:00Z»
$UtcTime2009c = Get-Date -Date «2009-11-29 5:00:00Z»
$UtcTime2010c = Get-Date -Date «2010-11-29 5:00:00Z»
$UtcTime2011c = Get-Date -Date «2011-11-29 5:00:00Z»
$UtcTime2012c = Get-Date -Date «2012-11-29 5:00:00Z»
$UtcTime2013c = Get-Date -Date «2013-11-29 5:00:00Z»
$UtcTime2014c = Get-Date -Date «2014-11-29 5:00:00Z»
$UtcTime2015c = Get-Date -Date «2015-11-29 5:00:00Z»
$UtcTime2016c = Get-Date -Date «2016-11-29 5:00:00Z»
$out = @()
$out += [pscustomobject]@{«year»=»2009»;»a»=$UtcTime2009;»b»=$UtcTime2009b;»c»=$UtcTime2009c}
$out += [pscustomobject]@{«year»=»2010»;»a»=$UtcTime2010;»b»=$UtcTime2010b;»c»=$UtcTime2010c}
$out += [pscustomobject]@{«year»=»2011»;»a»=$UtcTime2011;»b»=$UtcTime2011b;»c»=$UtcTime2011c}
$out += [pscustomobject]@{«year»=»2012»;»a»=$UtcTime2012;»b»=$UtcTime2012b;»c»=$UtcTime2012c}
$out += [pscustomobject]@{«year»=»2013»;»a»=$UtcTime2013;»b»=$UtcTime2013b;»c»=$UtcTime2013c}
$out += [pscustomobject]@{«year»=»2014»;»a»=$UtcTime2014;»b»=$UtcTime2014b;»c»=$UtcTime2014c}
$out += [pscustomobject]@{«year»=»2015»;»a»=$UtcTime2015;»b»=$UtcTime2015b;»c»=$UtcTime2015c}
$out += [pscustomobject]@{«year»=»2016»;»a»=$UtcTime2016;»b»=$UtcTime2016b;»c»=$UtcTime2016c}
$out
[…] Блог Ильи Сазонова […]