Windows: установка системного времени
В какой-то момент я обнаружил, что на одной из моих домашних машин с Windows 10 установлено некорректное время, часы отставали. Я проверил службу Windows Time, она была запущена, но, судя по всему, не работала. Затем я проверил вторую машину (ноутбук) и там ситуация оказалась аналогичной, то есть время не устанавливалось.
Сначала я попробовал решить проблему с помощью Gemini, тот довольно быстро сдался и предложил устанавливать время с помощью скрипта, время предполагалось получать через HTTP с одной из общедоступных служб. Тогда я обратился к ChatGPT, тот оказался гораздо более умным и мы провели исследования в результате которых он пришел к выводу, что не работает что-то именно в самой службе Windows. Мы проверяли обе машины, отпали блокировки портов и протокола UDP, был проверен мой роутер, все было в рабочем состоянии. После того как я потратил на решение проблемы целый день, я решил остановиться и таки да, подключил скрипт в планировщик для установки времени при запуске компьютера.
Фиксирую ряд моментов об этой службе.
В Windows за синхронизацию времени отвечает служба Windows Time (W32Time). В упрощённом виде она работает так:
Аппаратные часы компьютера
│
▼
W32Time
│
│ NTP/UDP 123
▼
NTP-сервер
time.windows.com
pool.ntp.org
и т.д.
│
▼
NTP-ответ
│
▼
расчёт смещения
│
▼
корректировка часов
Но внутри есть несколько важных механизмов.
1. При загрузке Windows
Компьютер получает первоначальное время из RTC/CMOS — аппаратных часов материнской платы.
Именно поэтому при:
w32tm /query /source
можно увидеть:
Local CMOS Clock
Это не означает, что CMOS является настроенным NTP-сервером. Это означает: последнего пригодного внешнего источника времени нет, поэтому система использует локальные часы.
2. W32Time выбирает источник
Настройка:
w32tm /query /configuration
показывает, например:
Type: NTP
NtpServer: time.windows.com,0x8
То есть W32Time должна обращаться к:
time.windows.com
по протоколу NTP.
Можно указать несколько серверов:
time.windows.com,0x8 pool.ntp.org,0x8 time.nist.gov,0x8
3. Используется UDP/123
Классический NTP использует:
UDP source port: 123
UDP destination port: 123
То есть W32Time создаёт NTP-сокет и отправляет примерно:
PC 192.168.0.103:123
│
│ UDP
▼
NTP 213.239.234.28:123
Сервер отвечает:
NTP 213.239.234.28:123
│
▼
PC 192.168.0.103:123
Обычный NTP-клиент может работать иначе:
192.168.0.103:59882 → 185.125.190.57:123
185.125.190.57:123 → 192.168.0.103:59882
А W32Time использует локальный порт 123.
4. W32Time не просто спрашивает «который час?»
NTP-пакет содержит временные метки.
Упрощённо:
T1 = время отправки запроса клиентом
T2 = время получения запроса сервером
T3 = время отправки ответа сервером
T4 = время получения ответа клиентом
По этим четырём значениям можно оценить:
задержку сети:
delay ≈ (T4 - T1) - (T3 - T2)
и смещение часов клиента:
offset ≈ ((T2 - T1) + (T3 - T4)) / 2
Поэтому NTP значительно сложнее простого:
«отправил запрос → получил время сервера → поставил его себе».
5. W32Time собирает несколько измерений
Windows не обязательно корректирует часы после одного ответа.
Она собирает NTP samples:
sample 1
sample 2
sample 3
...
Затем отбрасывает плохие/аномальные измерения и пытается получить надёжную оценку смещения.
6. Затем Windows корректирует часы
Если расхождение небольшое, Windows может плавно изменить скорость хода часов, чтобы постепенно привести их к правильному времени.
Если расхождение достаточно большое, возможна ступенчатая коррекция (step).
Поэтому W32Time — это не просто:
получил время → SetSystemTime()
а полноценный механизм регулирования системных часов.
7. Существует период опроса
В конфигурации можно увидеть:
MinPollInterval: 10
MaxPollInterval: 15
Это степени двойки:
2^10 = 1024 секунд
2^15 = 32768 секунд
То есть интервал может динамически изменяться примерно от:
17 минут
до:
9 часов
Кроме того, может быть:
SpecialPollInterval: 16384
Это примерно:
4 часа 33 минуты
Конкретное поведение зависит от режима и флагов peer'а.
Что происходит при w32tm /resync
Когда мы выполняем:
w32tm /resync
это не просто команда "скажи серверу время".
Она заставляет службу попытаться выполнить новую синхронизацию.
Упрощённо:
w32tm /resync
│
▼
W32Time
│
▼
выбрать peer
│
▼
отправить NTP-запрос
│
▼
получить ответ
│
▼
создать NTP sample
│
▼
проверить sample
│
▼
рассчитать offset
│
▼
скорректировать системные часы
Почему stripchart здесь очень важен
Команда:
w32tm /stripchart /computer:213.239.234.28 /dataonly /samples:3
тоже использует NTP, но это не тот же самый механизм синхронизации, что W32Time service.
Например:
19:58:08, +09.6895857s
19:58:10, +09.6929900s
19:58:12, +09.6926500s
Это доказывает:
DNS ✓
маршрутизация ✓
UDP/123 ✓
NTP-сервер ✓
ответ сервера ✓
Но это не доказывает, что W32Time сможет использовать этот ответ для собственной синхронизации.
И ещё одна важная деталь
W32Time создаёт сокеты:
[::]:123
0.0.0.0:123
То есть сама служба слушает порт UDP 123 на компьютере.
А stripchart может использовать другой сетевой путь/сокет.
Поэтому принципиальная разница сейчас выглядит так:
W32Time
│
source port 123
│
▼
router/NAT
│
▼
NTP server
│
▼
??? :123
│
▼
W32Time
против:
stripchart
│
ephemeral port
│
▼
router/NAT
│
▼
NTP server
│
▼
ephemeral port
│
▼
stripchart
Установка времени скриптом.
Создайте папку для скриптов, например C:\Scripts и в ней файл SyncTime.ps1 со следующим содержимым:
try {
$res = Invoke-WebRequest -Uri "https://ya.ru" -Method Head -TimeoutSec 5 -UseBasicParsing
$serverTime = [datetime]$res.Headers.Date
Set-Date $serverTime
} catch {
$res = Invoke-WebRequest -Uri "https://www.google.com" -Method Head -TimeoutSec 5 -UseBasicParsing
$serverTime = [datetime]$res.Headers.Date
Set-Date $serverTime
}
Сначала будет попытка получить время от Яндекса, если не получится, то от Google.
-
Нажмите
Win + R, введитеtaskschd.mscи нажмитеEnter(Планировщик заданий). -
Справа нажмите «Создать задачу...» (Create Task).
-
На вкладке «Общие»:
-
Имя:
HTTP Time Sync -
Обязательно выберите галочку: «Выполнить с наивысшими правами» (Run with highest privileges) — это нужно, чтобы у скрипта были права на изменение системного времени.
-
В поле «Настроить для» выберите Windows 10 (или Windows 11).
-
-
На вкладке «Триггеры»:
-
Нажмите «Создать...» -> В поле «Начать задачу» выберите «При запуске» (At startup) -> ОК.
-
«При подключении к сети» (On workstation unlock / или по событию сна) — чтобы время корректировалось, когда вы открываете крышку ноутбука или разблокируете экран.
-
-
На вкладке «Действия»:
-
Нажмите «Создать...» -> Действие: «Запуск программы» (Start a program).
-
В поле «Программа или сценарий» введите:
powershell.exe -
В поле «Добавить аргументы (необязательно)» введите:
-ExecutionPolicy Bypass -WindowStyle Hidden -File "C:\Scripts\SyncTime.ps1"
-
-
На вкладке «Условия» и «Параметры»:
-
Снимите галочку «Запускать задачу только при питании от электросети» (если это ноутбук).
-
Поставьте галочку «Запускать задачу как можно скорее после пропуска планового запуска».
-
No comments to display
No comments to display