Работа с временными зонами в Moment.js строится вокруг двух ключевых аспектов: преобразования времени между зонами и корректного форматирования с учётом смещений и идентификаторов IANA. Базовая библиотека Moment.js работает в локальной временной зоне окружения или в UTC, однако полноценная поддержка часовых поясов реализуется через расширение moment-timezone.
Moment.js хранит момент времени как количество миллисекунд с эпохи Unix (UTC). Это означает, что сам объект момента не «привязан» к конкретной временной зоне — зона применяется только при отображении и преобразовании.
Ключевая особенность:
const m = moment();
Здесь создаётся момент в локальной зоне системы. При этом значение внутри объекта остаётся UTC-эквивалентом.
Для работы с временными зонами используется расширение:
moment.tz
Основной принцип — указание IANA-идентификатора зоны:
Пример создания момента в конкретной зоне:
const m = moment.tz("2026-05-21 12:00", "Asia/Almaty");
В этом случае строка интерпретируется как локальное время указанной зоны, а не системы.
Форматирование выполняется методом format, однако зона
влияет на результат только после её установки.
const m = moment.tz("2026-05-21 12:00", "Asia/Almaty");
console.log(m.format("YYYY-MM-DD HH:mm"));
Вывод будет соответствовать времени в зоне Asia/Almaty.
Moment.js предоставляет несколько токенов для работы со смещениями:
Z — смещение в формате ±HH:mmZZ — смещение без двоеточия (±HHmm)const m = moment.tz("2026-05-21 12:00", "Asia/Almaty");
console.log(m.format("YYYY-MM-DD HH:mm Z"));
console.log(m.format("YYYY-MM-DD HH:mm ZZ"));
Смещение определяется относительно UTC и автоматически учитывает летнее/зимнее время, если оно применяется в выбранной зоне.
Одним из ключевых механизмов является метод tz для
изменения представления времени без изменения базового момента.
const utcTime = moment.utc("2026-05-21 12:00");
const moscow = utcTime.clone().tz("Europe/Moscow");
const tokyo = utcTime.clone().tz("Asia/Tokyo");
Важно различать:
moment.utc() — фиксирует UTC-режим.tz(zone) — переводит отображение в указанную зонуПри отсутствии moment-timezone:
moment().format();
используется локальная зона окружения (операционной системы).
При использовании moment-timezone:
moment.tz("2026-05-21 12:00", "Europe/London");
временная зона становится частью логики интерпретации строки.
Moment.js позволяет выводить краткое обозначение зоны:
z — краткое имя зоны (например, GMT, EST)const m = moment.tz("2026-05-21 12:00", "America/New_York");
console.log(m.format("YYYY-MM-DD HH:mm z"));
Следует учитывать, что z не всегда возвращает стабильное
значение для всех зон.
При конвертации важно сохранять исходный момент:
const base = moment.tz("2026-05-21 12:00", "Asia/Almaty");
const ny = base.clone().tz("America/New_York");
const london = base.clone().tz("Europe/London");
Каждый вызов clone() предотвращает мутацию исходного
объекта.
UTC часто используется как универсальный слой между временными зонами.
const local = moment.tz("2026-05-21 12:00", "Asia/Almaty");
const utc = local.clone().utc();
console.log(utc.format("YYYY-MM-DD HH:mm"));
После перевода в UTC дальнейшее преобразование в любую зону становится предсказуемым.
ISO-форматирование часто комбинируется с временными зонами:
const m = moment.tz("2026-05-21 12:00", "Asia/Almaty");
console.log(m.toISOString());
Метод toISOString всегда возвращает UTC, игнорируя
текущую зону отображения.
Разница между временными зонами может быть вычислена через
utcOffset:
const m = moment.tz("2026-05-21 12:00", "Asia/Almaty");
console.log(m.utcOffset());
Значение возвращается в минутах и позволяет выполнять арифметику времени:
const offsetHours = m.utcOffset() / 60;
Moment-timezone использует базу IANA, что позволяет автоматически учитывать DST:
const winter = moment.tz("2026-01-15 12:00", "Europe/Berlin");
const summer = moment.tz("2026-07-15 12:00", "Europe/Berlin");
console.log(winter.format("Z"));
console.log(summer.format("Z"));
Разные значения смещения отражают сезонные изменения.
Иногда требуется игнорировать правила временных зон и использовать фиксированный offset:
const m = moment().utcOffset("+03:00");
console.log(m.format("YYYY-MM-DD HH:mm Z"));
Такой подход не учитывает DST и используется в системах с фиксированным временем.
Для визуального сравнения удобно выводить одинаковую дату в разных зонах:
const base = "2026-05-21 12:00";
const zones = ["Asia/Almaty", "Europe/Moscow", "America/New_York"];
zones.forEach(z => {
console.log(moment.tz(base, z).format("YYYY-MM-DD HH:mm Z"));
});
Такой вывод позволяет увидеть реальную разницу во времени без дополнительных вычислений.
При последовательных вызовах важно учитывать порядок операций:
const m = moment.utc("2026-05-21 12:00")
.tz("Asia/Almaty")
.add(2, "hours")
.format("YYYY-MM-DD HH:mm Z");
Добавление времени происходит уже в контексте выбранной зоны, что влияет на итоговое значение.
Форматирование может сочетаться с локалями:
moment.locale("ru");
const m = moment.tz("2026-05-21 12:00", "Europe/Moscow");
console.log(m.format("LLLL Z"));
Локаль влияет на текстовые элементы (названия месяцев, дней), но не изменяет вычисления зоны.
Некоторые временные зоны изменяли свои правила в прошлом. IANA-база хранит такие изменения, поэтому результат форматирования зависит от года:
moment.tz("2010-05-21 12:00", "Europe/Moscow").format("Z");
Значение смещения для одной и той же зоны может отличаться в зависимости от исторического периода.
Наиболее устойчивый подход к форматированию:
const stored = moment.utc("2026-05-21 12:00");
const view = stored.clone()
.tz("Asia/Almaty")
.format("YYYY-MM-DD HH:mm Z");