Летнее время (Daylight Saving Time, DST) представляет собой сезонное смещение локального времени, при котором часы переводятся вперёд или назад на один час. В рамках JavaScript и среды выполнения это явление напрямую влияет на вычисления с датами, форматирование времени и интерпретацию локальных значений в различных часовых поясах.
Главная сложность заключается в том, что одно и то же календарное время может существовать в одном часовом поясе в разные периоды года, либо не существовать вовсе в момент перехода.
Часовые пояса с поддержкой летнего времени не являются статичными. Их смещение относительно UTC изменяется в зависимости от даты.
Пример поведения:
Это означает, что один и тот же локальный часовой формат может соответствовать разным моментам времени в UTC.
Ключевая проблема:
При переходе на летнее время локальные часы перескакивают вперёд.
Например:
Часовой диапазон 02:00–02:59 не существует.
Следствие:
При переходе на стандартное время часы возвращаются назад:
Диапазон 02:00–02:59 возникает дважды.
Следствие:
Intl.DateTimeFormat — основной механизм форматирования
дат с учётом локали и временной зоны.
Базовая конфигурация:
const formatter = new Intl.DateTimeFormat("ru-RU", {
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
timeZone: "Europe/Moscow"
});
Ключевая особенность:
При использовании timeZone движок Jav * aScript:
Пример:
const date = new Date("2026-06-01T12:00:00Z");
console.log(
new Intl.DateTimeFormat("en-GB", {
timeZone: "Europe/Berlin",
hour: "2-digit",
minute: "2-digit"
}).format(date)
);
В зависимости от сезона будет применено либо UTC+1, либо UTC+2.
Объект Date в JavaScript хранит время в виде UTC
timestamp.
const d = new Date("2026-03-29T02:30:00");
Если указанное локальное время попадает в несуществующий диапазон (переход на летнее время), поведение зависит от реализации:
Важное свойство:
Date не хранит информацию о временной зонеUTC остаётся неизменным эталоном:
Пример:
| Локальное время (Berlin) | UTC |
|---|---|
| 12:00 (зима) | 11:00 |
| 12:00 (лето) | 10:00 |
Из-за этого один и тот же локальный час соответствует разным моментам UTC в течение года.
Intl использует системные данные IANA:
Эти базы содержат:
При форматировании:
new Intl.DateTimeFormat("en-US", {
timeZone: "America/New_York",
hour: "2-digit",
hour12: false
}).format(new Date("2026-07-01T12:00:00Z"));
летнее смещение применяется автоматически без дополнительных настроек.
DST создаёт проблему сравнения локальных значений.
Пример:
В JavaScript корректное сравнение возможно только через UTC:
const a = new Date("2026-11-01T01:30:00-04:00");
const b = new Date("2026-11-01T01:30:00-05:00");
console.log(+a === +b); // false
Intl.DateTimeFormat не маркирует явно летнее время, но
его эффект проявляется в:
Для получения смещения используется:
const dtf = new Intl.DateTimeFormat("en-US", {
timeZone: "Europe/London",
timeZoneName: "longOffset"
});
dtf.format(new Date());
Особое внимание требуется к моментам перехода:
При работе с интервалами важно учитывать, что DST может изменять длительность суток:
Пример проблемы:
const start = new Date("2026-03-28T00:00:00");
const end = new Date("2026-03-29T00:00:00");
console.log((end - start) / 3600000);
Результат может отличаться от 24 часов в зависимости от зоны.
Intl разделяет два независимых аспекта:
ru-RU, en-US) — формат выводаEurope/Paris) — календарная модель
времениDST относится исключительно ко второму аспекту и не зависит от языка.
Разные регионы ведут разные политики:
Следствие:
Intl.DateTimeFormat может давать
разные смещения в зависимости от зоныПри работе с форматированием:
Исторические даты могут отображаться иначе в зависимости от актуальной базы часовых поясов среды выполнения.
Ключевая проблема DST в JavaScript заключается в разделении:
Intl решает задачу отображения, но не решает задачу
календарной арифметики.
Поэтому: