Вслед за Россией правительства Украины*, Беларуси и Армении решили отменить переход на сезонное время в конце октября 2011 года. Однако такое решение было принято намного позднее чем в России, в результате чего на подготовку к этому событию осталось мало времени. Компания Майкрософт выпустила обновление Windows, где изменяются часовые пояса в России- KB2570791, а вот для Армении, Украины и Беларуси такого обновления пока нет. Майкрософт обещает выпустить его в декабре 2011 года. Кроме того, для Windows 2000 обновлений нет, и помощи смогут ждать только счастливые обладатели Microsoft Services Premier Support.
В связи с этим в Интернет появилось множество советов по выходу из этой ситуации. Майкрософт, например, предлагает воспользоваться аналогичными часовыми поясами стран, где сезонное время уже отменено: (+03:00) Калининград для Украины и Беларуси или (+05:00) Ташкент для Армении, соответственно. Мне понравился вариант предлагаемый Дмитрием Булановым в его статье на OsZone.net.
Однако вариант REG- файла предложенный им некорректно отрабатывал на Windows XP, а использование REG-файла усложняло использование предпочтений групповой политики.
Изучив документацию, я написал свой вариант скрипта для изменения часового пояса. Но обо всем по порядку.
* 19 октября 2011 года правительство Украины решило отменить решение об отмене перехода на зимнее время. Таким образом жителям этой страны изменять часовой пояс в этом году не понадобиться.
Теория
За назначение и корректное отображение часового пояса в реестре Windows отвечает раздел
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\*Имя часового пояса*
В зависимости от версии операционной системы в нем хранятся параметры, определяющие конкретный часовой пояс.
Для Windows XP/2003 это параметры:
- Display
- Dlt
- Std
- Index
- MapID
- TZI
Для Windows Vista и выше добавились еще несколько параметров:
- MUI_Display
- MUI_Std
- MUI_Dlt
Нас интересуют параметры, которые критичны для смены часового пояса:
Display – отвечает за отображение часового пояса в списке выбора часовых поясов.
Dlt – задает название летнего времени.
Std – "Стандартное" зимнее время.
TZI – Самый важный параметр. Это база данных о временном смещении, времени перехода на летнее время и т.д. Из этого параметра каждый раз при смене часового пояса создаются параметры в разделе реестра
HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation
Вот как описывается структура ключа TZI на MSDN:
typedef struct _REG_TZI_FORMAT
{
LONG Bias;
LONG StandardBias;
LONG DaylightBias;
SYSTEMTIME StandardDate;
SYSTEMTIME DaylightDate;
} REG_TZI_FORMAT;
Таким образом, в одном бинарном ключе перечисляются следующие параметры: Bias, StandardBias, DaylightBias, StandardDate, DaylightDate. О значении этих параметров также можно прочесть на MSDN.
В зависимости от языка и версии Windows, в раздел TimeZoneInformation копируются параметры отображения часовой зоны в графическом интерфейсе. В Windows XP эти значения берутся из ключей реестра Display, Dlt, Std, а начиная с Vista из соответствующей библиотеки локализации(MUI). Однако для совместимости остаются и старые параметры Display, DaylightName и т.д.
Сопоставление параметров в разделах TimeZone и TimeZoneInformation видно на картинке, взятой из интересной статьи в блоге BCL Team:
Что интересно, начиная с Windows Vista, Майкрософт отказалась от карты в окне смене часового пояса, а ведь эта карта была там, начиная с Windows 95, и для каждого часового пояса в реестре хранились координаты.
В реестре есть также раздел:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\*Имя часового пояса*\DYNAMIC DST (DYNAMIC DAYLIGHT SAVING TIME)
Этот раздел хранит историю изменений часовых поясов по годам. Windows XP и Windows Server 2003 обновляют этот ключ посредством накопительных обновлений. Для Windows 2000 такая поддержка прекращена. Хотя это не значит, что нельзя изменить эти значения вручную.
Резюме теоретической части
Теперь можно сделать алгоритм создания часового пояса для любой точки земного шара:
- Необходимо создать новый раздел реестра в ветке HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones для вашего часового пояса. В моем случае это Minsk Standard Time.
- Задать корректные значения параметров Display, Dlt, Std, TZI.
- Изменить часовой пояс на вновь созданный, каким- либо способом (далее описаны возможные варианты).
Скрипт для изменения часового пояса
Я написал для вас небольшой скрипт, который можно использовать для смены любого часового пояса. Чтобы изменить его под свой часовой пояс, необходимо изменять русскоязычное написание часового пояса в кодировке OEM 866, а затем сохранить скрипт в кодировке ANSI 1251. Например, если вы используете для редактирования программу Notepad2, то редактирование с помощью быстрых клавиш будет выглядеть так:
- Открыть скрипт;
- Ctrl+A (Выделить все);
- Ctrl+Shift+O (Преобразовать текст в кодировку OEM 866);
- Отредактировать русскоязычные названия часового пояса и параметры для вашего часового пояса;
- Ctrl+A (Выделить все);
- Ctrl+Shift+A (Преобразовать текст в кодировку ANSI 1251);
- Ctrl+S (Сохранить)
Другие способы сохранения в кодировке OEM смотрите здесь.
Загрузите архив со скриптом с OsZone.net: скачать, либо скопируйте текст скрипта ниже в Блокнот и сохраните его в кодировке ANSI как tz.cmd:
@Echo off
Rem Belarus timezone change utility(UTC+3 Minsk)
Rem (c) Azarov Denis 01/10/2011
Rem mail to volk1234@mail.ru
Rem forum page http://www.oszone.net/16420/Daylight_Saving_Time
Rem v 0.5 15.10.2011
:set_start_time
Set start_time=%TIME:~0,-3%
Set start_time=%start_time::=%
Set start_time=%start_time: =0%
Set start_time=%DATE:~-4%%DATE:~3,2%%DATE:~0,2%_%start_time%
Rem Detecting OS,language and current tz registry key name
:DetectEnv
For /F "Tokens=3" %%A In ('Reg Query "HKLM\SYSTEM\CurrentControlSet\Control\Nls\Language" /V InstallLanguage') Do Set OSLang=%%A
For /F "Tokens=3*" %%A In ('Reg Query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /V CurrentVersion') Do Set OSver=%%A
If %OSver% GTR 5.2 (
Set Regkey4=HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation
) Else (
Set Regkey4=HKCU\Software\Microsoft\Windows NT\CurrentVersion\Time Zones
)
For /F "Tokens=2*" %%i In ('Reg Query "%Regkey4%" /V TimeZoneKeyName 2^>nul^|find /i "REG_SZ" 2^>nul') Do Set TZKN=%%j
If %OSver% == 5.2 Set TZKN=E. Europe Standard Time
Rem windows 2003r2 whithout updates had 'GTB Standart Time' timezonename for Minsk, not E. Europe Standard Time. And it have not tzchange util.
Rem Setting Variables
:TZVARS
Set Regkey1=HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\%TZKN%
Set Regkey2=HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation
Set TZIdata="4cffffff00000000c4ffffff0000000000000000000000000000000000000000000000000000000000000000"
Set TZIdata2="88ffffff00000000c4ffffff00000a0000000500030000000000000000000300000005000200000000000000"
Set Dllres1="@tzres.dll,-1730"
Set Dllres2="@tzres.dll,-1731"
Set Dllres3="@tzres.dll,-1732"
Set DisplayEn="(UTC+03:00) Minsk"
Set DisplayRu="(UTC+03:00) ЊЁбЄ"
Set DltEn=Minsk Daylight Time
Set StdEn=Minsk Standard Time
Set DltRu=ЊЁбЄ®Ґ ўаҐ¬п («Ґв®)
Set StdRu=ЊЁбЄ®Ґ ўаҐ¬п (§Ё¬ )
Set Backupdir="%TEMP%\TZBY\%start_time%"
Set Regkey3=HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\%StdEn%
If "%OSLang%"=="0419" (
Goto :LangRu
) Else (
Goto :LangEn
)
:LangRu
Set DLT=%DltRu%
Set STD=%StdRu%
Set DSPL=%DisplayRu%
Goto :Regbackup
:LangEn
Set DLT=%DltEn%
Set STD=%StdEn%
Set DSPL=%DisplayEn%
Rem Backup regisry
:Regbackup
If Not Exist %Backupdir% MD %Backupdir%
REG EXPORT "%Regkey1%" %Backupdir%\TZ.reg >nul
REG EXPORT "%Regkey2%" %Backupdir%\TZI.reg >nul
Echo @Echo Off>>%Backupdir%\restore_tz.cmd
Echo. >>%Backupdir%\restore_tz.cmd
Echo Regedit /s TZ.reg>>%Backupdir%\restore_tz.cmd
Echo Regedit /s TZI.reg>>%Backupdir%\restore_tz.cmd
Echo Reg Delete "%Regkey3%" /f>>%Backupdir%\restore_tz.cmd
Echo. >>%Backupdir%\restore_tz.cmd
If %OSver% LEQ 5.2 (
Echo Tzchange /c "%TZKN%">>%Backupdir%\restore_tz.cmd
)
If %OSver% GTR 5.2 (
Echo Tzutil /s "%TZKN%">>%Backupdir%\restore_tz.cmd
)
Echo. >>%Backupdir%\restore_tz.cmd
Echo Exit /b0>>%Backupdir%\restore_tz.cmd
Rem Main: making settings for timezone utc +0300 Minsk
:SettingTZ
REG ADD "%Regkey3%" /v Dlt /t REG_SZ /d "%STD%" /f >nul
REG ADD "%Regkey3%" /v Std /t REG_SZ /d "%STD%" /f >nul
REG ADD "%Regkey3%" /v Display /t REG_SZ /d %DSPL% /f >nul
REG ADD "%Regkey3%\Dynamic DST" /v 2010 /t REG_BINARY /d %TZIdata2% /f >nul
REG ADD "%Regkey3%\Dynamic DST" /v 2011 /t REG_BINARY /d %TZIdata% /f >nul
REG ADD "%Regkey3%\Dynamic DST" /v FirstEntry /t REG_DWORD /d 0x000007da /f >nul
REG ADD "%Regkey3%\Dynamic DST" /v LastEntry /t REG_DWORD /d 0x000007db /f >nul
REG ADD "%Regkey3%" /v TZI /t REG_BINARY /d %TZIdata% /f >nul
If %OSver% GTR 5.2 (
REG ADD "%Regkey3%" /v MUI_Display /t REG_SZ /d %Dllres1% /f >nul
REG ADD "%Regkey3%" /v MUI_Std /t REG_SZ /d %Dllres2% /f >nul
REG ADD "%Regkey3%" /v MUI_Dlt /t REG_SZ /d %Dllres3% /f >nul
REG ADD "%Regkey2%" /v StandardName /t REG_SZ /d %Dllres2% /f >nul
REG ADD "%Regkey2%" /v DaylightName /t REG_SZ /d %Dllres2% /f >nul
REG ADD "%Regkey2%" /v DynamicDaylightTimeDisabled /t REG_DWORD /d 0x00000001 /f >nul
REG ADD "%Regkey2%" /v TimeZoneKeyName /t REG_SZ /d "%StdEn%" /f >nul
tzutil /s "%StdEn%"
)
If %OSver% LEQ 5.2 (
tzchange /c "%StdEn%"
)
Exit /b0
Немного о том, как работает скрипт. Он определяет Ваш текущий часовой пояс и делает резервную копию нужных разделов реестра. Путь к резервной копии: %Temp%\TZBY\дата и время запуска. Для восстановления прежних настроек необходимо запустить файл restore _tz.cmd.
Важно! В Windows Server 2003R2 после чистой установке отсутствует утилита tzchange и отличается часовой пояс - вместо текущего E. Europe Standard Time установлен GTB Standart time. Если все необходимые обновления установлены, то скрипт отработает корректно.
Важно! При выходе официального обновления для часового пояса настоятельно рекомендуется восстановить старые настройки и затем применить обновление.
Затем скрипт изменяет часовой пояс в зависимости от версии ОС (XP/2003/Vista/7/2008R2) и языка (RUS\ENG).
Основной проблемой при изменении часового пояса через скрипт была установка этого пояса активным. В Windows XP/2003 и Windows 7 существуют утилиты командной строки tzchange и tzutil соответственно.
В Windows Vista такие утилиты отсутствуют, и сменить часовой пояс можно через GUI, либо попробовать изменение название на нужное командой
control timedate.cpl,,/Z Minsk Standard Time"
Добавлено позднее: Как оказалось, компания Майрософт прислушалась к просьбам пользователей и выпустила обновление KB2556308 которое добавляет в операционные системы Windows Vista и Windows Server 2008 утилиту tzutil. После установки этого обновления, скрипт для смены часового пояса отработает как надо.
Также пользователям Windows 2000 можно воспользоваться специальной утилитой TzEdit (прямая ссылка на загрузку). для редактирования часового пояса вручную.
Есть еще способ сделать созданную зону активной - это явно указать ее название в параметре TimeZoneKeyName и перезагрузить компьютер. В Windows XP/2003 и Vista/7/2008R2 этот параметр находится в разных местах реестра:
В Windows XP/2003:
HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Time Zones
[REG_SZ] TimeZoneKeyName = Minsk Standart Time
В Windows Vista/7/2008R2:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation[REG_SZ] TimeZoneKeyName= Minsk Standart Time
Если вы хотите выполнить скрипт на всех компьютерах в организации, находящейся в домене, применяйте предпочтения групповых политик для настройки запуска скрипта, например, через планировщик заданий. Как это сделать, описано здесь.
В конце хотелось бы заметить, что ручное изменение часового пояса не решит проблем с такими программами как Exchange, Outlook, SQL и т.д. Для некоторых из этих программ уже есть утилиты или исправления, для других еще разрабатываются.
Если у Вас есть вопросы по статье вы можете задать их в этом блоге.
Полезные ссылки
- Центр справки и поддержки по переходу на летнее и зимнее время;
- Объявление Майкрософт касаемо отмены сезонного времени в Армении, Беларуси и Украине;
- Статья KB2625508 в базе знаний;
- TIME_ZONE_INFORMATION structure на MSDN;
- Статья, описывающая смену часовых поясов в 2008 году в США и Канаде;
- Microsoft Daylight Saving Time & Time Zone Blog;
- Настройка перехода на летнее время в операционных системах Microsoft Windows;