Главная > Administration, MCP > Скрипт для изменения часовых поясов Украины, Беларуси и Армении

Скрипт для изменения часовых поясов Украины, Беларуси и Армении


Эту статью я опубликовал на OsZone.net, выкладываю и сюда для участников нашего клуба. Буду рад услышать ваше мнение по теме.

Денис.

Важно: В декабре компания Майкрософт выпустила накопительное  обновление для часовых поясов, в т.ч. для Беларуси. Рекомендуется использовать его, а данную статью использовать в познавательных целях.


Вслед за  Россией правительства Украины*, Беларуси и Армении решили отменить переход на сезонное время в конце октября 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 такая поддержка прекращена. Хотя это не значит, что нельзя изменить эти значения вручную.

Резюме теоретической части

Теперь можно сделать алгоритм создания часового пояса для любой точки земного шара:

  1. Необходимо создать новый раздел реестра в ветке HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones для вашего часового пояса. В моем случае это Minsk Standard Time.
  2. Задать корректные значения параметров Display, Dlt, Std, TZI.
  3. Изменить часовой пояс на вновь созданный, каким- либо способом (далее описаны возможные варианты).

Скрипт для изменения часового пояса

Я написал для вас небольшой скрипт, который можно использовать для смены любого часового пояса. Чтобы изменить его под свой часовой пояс, необходимо изменять русскоязычное написание часового пояса  в кодировке OEM 866, а затем сохранить скрипт в кодировке ANSI 1251. Например, если вы используете для редактирования программу Notepad2, то редактирование с помощью быстрых клавиш будет выглядеть так:

  1. Открыть скрипт;
  2. Ctrl+A (Выделить все);
  3. Ctrl+Shift+O (Преобразовать текст в кодировку OEM 866);
  4. Отредактировать русскоязычные названия часового пояса и параметры для вашего часового пояса;
  5. Ctrl+A (Выделить все);
  6. Ctrl+Shift+A (Преобразовать текст в кодировку ANSI 1251);
  7. 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 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) и языка (RUSENG).

Основной проблемой при изменении часового пояса через скрипт была установка этого пояса активным. В 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 и Vista\7\2008R2 этот ключ находиться в разных местах реестра:

В Windows XP:

HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Time Zones

[REG_SZ] TimeZoneKeyName = Minsk Standart Time

В WindowsVista\7\2008R2:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation

[REG_SZ] TimeZoneKeyName= Minsk Standart Time

Если вы хотите выполнить скрипт на всех компьютерах в организации, находящейся в домене, применяйте предпочтения групповых политик для настройки запуска скрипта, например, через планировщик заданий. Как это сделать, описано здесь.

В конце хотелось бы заметить, что ручное изменение часового пояса не решит проблем с такими программами как Exchange, Outlook, SQL и т.д. Для некоторых из этих программ уже есть утилиты или исправления, для других еще разрабатываются.

Полезные ссылки

  1. Центр справки и поддержки по переходу на летнее и зимнее время;
  2. Объявление Майкрософт касаемо отмены сезонного времени в Армении, Беларуси и Украине;
  3. Статья KB2625508 в базе знаний;
  4. TIME_ZONE_INFORMATION structure на MSDN;
  5. Статья, описывающая смену часовых поясов в 2008 году в США и Канаде;
  6. Microsoft Daylight Saving Time & Time Zone Blog;
  7. Настройка перехода на летнее время в операционных системах Microsoft Windows;
  1. Дмитрий
    20 октября 2011 в 20:19

    Здравствуйте Денис.
    Я уже отписался по поводу вашего скрипта на oszone, а тут хотелось бы уточнить один момент.
    Вы ведь правили ресурсы библиотеки tzres.dll?
    А скрипт restore_tz.cmd всего лишь запускает восстановление ключей реестра.
    Каким образом мы будем возвращать чекбокс «автоматический переход бла-бла..»?
    Наше с вами правительство, имхо, ещё более безумное чем в Украине, поэтому не возникнет ли вопрос 29 числа: «вяртай усё взад!» 🙂

    • 20 октября 2011 в 20:49

      1. Где именно отписались на осзоне ?
      2. Я не правил никаких ресурсов, все через настройки ключа TZI — там указывается смещение летнего времени=0 и галочка сама пропадает.
      3. Соответственно запустив бэкап вы возвращаете галочку на место.
      4. В свете последних принятых законодательных актов я не буду коментировать последнее ваше замечание. 🙂

  2. Дмитрий
    20 октября 2011 в 20:25

    Ах да 🙂
    Ещё нужно убрать из скрипта слово «зима»
    Какая уж тут зима 🙂
    В этом плане, тот скрипт что я положил на http://ifolder.ru/26469671
    выглядит веселее 🙂

  3. 20 октября 2011 в 20:53

    Дмитрий, я сделал так, как сделало Майкрософт для Росии. Там например Калининградское время (зима). По английски все гораздо понятнее Standart Time — «нормальное» время или по русски зимнее. Просто будет отображаться и зимой и летом слово зима. Но это не я придумал- а МС.
    Единственная вольность которую я себе позволил это правильно назвать часовой пояс UTC+03:00 поскольку GMT уже в 80-х годах отменили.

  4. Дмитрий
    20 октября 2011 в 22:06

    1. отписал отзыв под вашей статьёй
    2.в скрипте указаны даже строки:
    Set Dllres1=»@tzres.dll,-1730″
    Set Dllres2=»@tzres.dll,-1731″
    Set Dllres3=»@tzres.dll,-1732″
    хотя Resource Hacker не показывает мне их.
    3. сомневаюсь
    4. зря 🙂 пусть они нас боятся

  5. 20 октября 2011 в 22:11

    2. Это сделано что бы обмануть Win7 и она не пыталась умничать показывая неправильный часовой пояс. Цифры могут быть любыми лишбы ресурс не существовал в dll.
    3. что же мешает проверить. Кстати мой скрипт не удаляет старую зону, можно «побаловаться» переключаясь между Минск +02 и Минск +03 заодно и на галочку посмотрите.
    4. Это тематический блог.Точка.

    • Юрий
      30 октября 2011 в 14:45

      mcpclubminsk :
      мой скрипт не удаляет старую зону, можно «побаловаться»

      Ждем версию скрипта, «без баловства»), которая удаляет старую зону +02. Спасибо.

      • 30 октября 2011 в 16:26

        Я не вижу никаких проблем кроме эстетических в существовании в списке двух зон (GMT+02:00)Минск и (UTC+03:00)Минск.
        Ведь в декабре будет накопительное обновление- восстановите настройки, примените обновление и забудете про проблемы. При восстановлении настроек зона создаваемая моим скриптом удаляется.

        Если Вам принципиально, добавьте в скрипт перед командой Exit /b0
        строку
        Reg Delete «%Regkey1%» /f

  6. Дмитрий
    20 октября 2011 в 22:25

    Забыл сказать.
    Опера неверно отображает содержимое кода на осзоне.
    Поэтому при копировании и последующей смене кодировки у многих вылезет ошибка.
    Случайно обнаружил. После трёх неудачных попыток 🙂

  7. 20 октября 2011 в 22:26

    Я добавил ссылку на скачивание скрипта с осзона.

  8. Andrei
    24 октября 2011 в 14:05

    Добрый день!
    Спасибо за проделанный труд: составление скрипта (хоть и делали Вы скрипт для себя, но выложили и всё описали для каждого интересующегося) ).
    Можно озвучить два момента:
    1. Как Вы думаете, в декабре Microsoft при выпуске обновления какое название будет использовать и не будет ли конфликта при установке обновления с таким же) Minsk Standart Time

    2. При запуске на контроллере домена (тестовый windows 2003 R2 Enterpr Edition Service Pack 2) restore_tz.cmd и TZI.reg создаются, а TZ.reg — не создаётся, при выполнении скрипта tz_by.cmd на строке REG EXPORT «%REGKEY1%» … пишет ошибка:
    Неверный синтаксис. Введите «REG EXPORT /?» для получения справки по использованию.
    Может дело в TZKN — не получается выяснить. А всё остальное — ок!

  9. 24 октября 2011 в 22:24

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

    Reg Delete «%Regkey3%» /f>>%Backupdir%\restore_tz.cmd

    2. К сожалению в 2003 сервере отсутствует ключ TimeZoneKeyName и скрипт не может определить текущую врменную зону- отсюда и ошибка.
    Дернулся я в сторону wmi, нашел скрипт на Powershell, а потом махнул рукой- через 2 меяца всем будет все равно- выйдет обновление 🙂

  10. 24 октября 2011 в 22:26

    А вообще если убрать %TZKN% из скрипта и заменить статическим именем часового пояса — например E. Eastern Europe (кстати в 2003 сервере R2 без обновлений (чистая установка, эта зона еще не Минска, а Бухареста) 🙂

  11. 29 октября 2011 в 19:25

    Изменил скрипт для корректной работы с windows 2003 R2.
    К сожалению не все так просто:
    «Важно! В Windows Server 2003R2 после чистой установке отсутствует утилита tzchange и отличается часовой пояс – вместо текущего E. Europe Standard Time установлен GTB Standart time. Если все необходимые обновления установлены, то скрипт отработает корректно.»

    Однако думаю если человек интересуется сменой часовых поясов на сервере установлены последние обновления…

  12. Сергей
    8 декабря 2011 в 17:51

    Спасибо за скрипт!
    Здорово сэкономил время. В компании осталось много машин под управлением win2k — для них скрипт стал вообще находкой.

  1. No trackbacks yet.

Ответить на mcpclubminsk Отменить ответ