Библиотека js-joda предоставляет современную модель
работы с датой и временем, вдохновлённую API java.time из
Java 8. Базовый пакет @js-joda/core содержит классы для
локальных дат, времени и временных отметок, однако не включает
полноценную поддержку часовых поясов IANA.
Пакет @js-joda/timezone добавляет:
Europe/Moscow,
Asia/Almaty);Без js-joda-timezone объект ZonedDateTime
способен работать только с фиксированными смещениями
(+03:00, UTC), но не с реальными мировыми
часовыми зонами.
npm install @js-joda/core @js-joda/timezone
Подключение:
const {
ZonedDateTime,
LocalDateTime,
ZoneId,
Instant
} = require('@js-joda/core')
require('@js-joda/timezone')
Импорт timezone-пакета обязателен. Он расширяет функциональность
ZoneRulesProvider и подключает базу временных зон.
В библиотеке существуют два разных понятия:
| Тип | Пример | Назначение |
|---|---|---|
ZoneOffset |
+05:00 |
фиксированное смещение |
ZoneId |
Asia/Almaty |
реальная временная зона |
const { ZoneOffset } = require('@js-joda/core')
const offset = ZoneOffset.of('+05:00')
console.log(offset.toString())
Результат:
+05:00
Такое смещение не учитывает летнее время и изменения правил.
const zone = ZoneId.of('Asia/Almaty')
console.log(zone.id())
Результат:
Asia/Almaty
Такая зона использует правила IANA и автоматически учитывает исторические изменения времени.
js-joda-timezone использует базу:
tz database (Olson database)
Она содержит:
Примеры зон:
Europe/Berlin
America/New_York
Asia/Tokyo
Asia/Almaty
UTC
const zone = ZoneId.of('Europe/Moscow')
const utc = ZoneId.of('UTC')
console.log(zone.id())
const dateTime = LocalDateTime.of(
2025,
3,
10,
14,
30
)
const zone = ZoneId.of('Asia/Almaty')
const zoned = dateTime.atZone(zone)
console.log(zoned.toString())
Результат:
2025-03-10T14:30+05:00[Asia/Almaty]
Объект содержит:
Пример:
2025-03-10T14:30+05:00[Asia/Almaty]
Разбор:
| Часть | Значение |
|---|---|
2025-03-10 |
дата |
14:30 |
время |
+05:00 |
смещение |
Asia/Almaty |
зона |
const now = ZonedDateTime.now(
ZoneId.of('Europe/Berlin')
)
console.log(now.toString())
Метод сохраняет абсолютный момент времени.
const tokyo = ZonedDateTime.now(
ZoneId.of('Asia/Tokyo')
)
const london = tokyo.withZoneSameInstant(
ZoneId.of('Europe/London')
)
console.log(tokyo.toString())
console.log(london.toString())
Пример результата:
2025-03-10T21:00+09:00[Asia/Tokyo]
2025-03-10T12:00Z[Europe/London]
Момент времени одинаковый, отображение разное.
Метод сохраняет локальное время.
const localChanged = tokyo.withZoneSameLocal(
ZoneId.of('Europe/London')
)
Теперь:
21:00 в Токио
станет:
21:00 в Лондоне
Абсолютный момент времени изменится.
UTC играет ключевую роль при хранении времени в распределённых системах.
const utcTime = ZonedDateTime.now(
ZoneId.of('UTC')
)
const local = utcTime.withZoneSameInstant(
ZoneId.of('Asia/Almaty')
)
Instant не содержит информации о часовом поясе.
Он представляет:
точку времени на временной шкале UTC
const instant = Instant.now()
const zoned = instant.atZone(
ZoneId.of('Europe/Paris')
)
console.log(zoned.toString())
const zoned = ZonedDateTime.now(
ZoneId.of('America/New_York')
)
console.log(zoned.offset().toString())
Пример:
-04:00
Одно из главных преимуществ js-joda-timezone —
автоматическая работа с переходами DST.
В некоторых странах время перескакивает:
02:00 -> 03:00
Попытка создать несуществующее время:
const dateTime = LocalDateTime.of(
2025,
3,
30,
2,
30
)
const zone = ZoneId.of('Europe/Berlin')
const zoned = dateTime.atZone(zone)
console.log(zoned.toString())
Библиотека автоматически скорректирует значение согласно правилам зоны.
При переводе часов назад время может повторяться дважды.
Например:
02:30
может существовать:
js-joda-timezone использует правила зоны для выбора
корректного смещения.
const zone = ZoneId.of('Europe/Berlin')
const rules = zone.rules()
const instant = Instant.now()
const offset = rules.offset(instant)
console.log(offset.toString())
const isDst = rules.isDaylightSavings(
Instant.now()
)
console.log(isDst)
const duration = rules.daylightSavings(
Instant.now()
)
console.log(duration.toString())
const zones = ZoneId.getAvailableZoneIds()
console.log(zones)
Результат:
Set(596) { ... }
function zoneExists(id) {
return ZoneId
.getAvailableZoneIds()
.has(id)
}
console.log(
zoneExists('Asia/Almaty')
)
const zoned = ZonedDateTime.parse(
'2025-03-10T14:30:00+05:00[Asia/Almaty]'
)
console.log(zoned.toString())
console.log(zoned.toString())
const {
DateTimeFormatter
} = require('@js-joda/core')
const formatter =
DateTimeFormatter.ofPattern(
'yyyy-MM-dd HH:mm z'
)
console.log(
zoned.format(formatter)
)
Пример:
2025-03-10 14:30 ALMT
| Символ | Значение |
|---|---|
z |
короткое имя |
zzzz |
полное имя |
X |
ISO offset |
VV |
идентификатор зоны |
const formatter =
DateTimeFormatter.ofPattern(
'yyyy-MM-dd HH:mm:ss VV'
)
console.log(
zoned.format(formatter)
)
Частая задача:
пользователь вводит локальное время
Необходимо:
const localDateTime =
LocalDateTime.parse(
'2025-05-01T15:00'
)
const userZone =
ZoneId.of('Asia/Almaty')
const utc = localDateTime
.atZone(userZone)
.withZoneSameInstant(
ZoneId.of('UTC')
)
console.log(utc.toString())
Распространённая архитектура:
| Данные | Формат |
|---|---|
| хранение | UTC |
| API | ISO-8601 |
| отображение | локальная зона |
const serverTime =
Instant.parse(
'2025-05-01T10:00:00Z'
)
const clientTime =
serverTime.atZone(
ZoneId.of('Asia/Almaty')
)
console.log(clientTime.toString())
Преимущество js-joda-timezone перед обычным
Date заключается в поддержке исторических правил.
Например:
const json = JSON.stringify({
meeting: zoned.toString()
})
const parsed = JSON.parse(json)
const meeting =
ZonedDateTime.parse(
parsed.meeting
)
| Возможность | Date | js-joda-timezone |
|---|---|---|
| неизменяемость | нет | да |
| IANA зоны | ограниченно | полноценно |
| DST | нестабильно | корректно |
| API | устаревший | современный |
| предсказуемость | низкая | высокая |
Все объекты js-joda неизменяемы.
const original =
ZonedDateTime.now(
ZoneId.of('UTC')
)
const changed =
original.plusHours(5)
console.log(original.toString())
console.log(changed.toString())
Исходный объект не изменится.
const result = zoned.plusHours(5)
const result = zoned.plusDays(3)
const result = zoned.minusMonths(1)
Добавление суток и добавление 24 часов — разные операции.
zoned.plusDays(1)
Сохраняет локальное время.
zoned.plusHours(24)
Добавляет фиксированное количество часов.
При переходах DST результаты могут отличаться.
a.equals(b)
Сравниваются:
a.isEqual(b)
Сравнивается только абсолютный момент времени.
const tokyo = ZonedDateTime.parse(
'2025-03-10T21:00+09:00[Asia/Tokyo]'
)
const london = ZonedDateTime.parse(
'2025-03-10T12:00Z[Europe/London]'
)
console.log(
tokyo.equals(london)
)
console.log(
tokyo.isEqual(london)
)
Результат:
false
true
js-joda-timezone особенно полезен:
Библиотека работает и в браузере.
Пример:
import {
ZonedDateTime,
ZoneId
} from '@js-joda/core'
import '@js-joda/timezone'
const zone =
Intl.DateTimeFormat()
.resolvedOptions()
.timeZone
console.log(zone)
Интеграция:
const userZone = ZoneId.of(zone)
Ошибка:
unsupported ZoneId
Причина:
require('@js-joda/timezone')
не был импортирован.
Нежелательно смешивать:
Date;Instant;LocalDateTime.Лучше хранить время в Instant или
ZonedDateTime.
LocalDateTime не содержит:
Для глобальных приложений этого недостаточно.
Использовать:
Instant или UTC
Конвертировать в:
ZonedDateTime пользователя
Передавать:
ISO-8601
Пример:
2025-05-01T10:00:00Z
const meetingLocal =
LocalDateTime.of(
2025,
6,
1,
15,
0
)
const organizerZone =
ZoneId.of('Europe/Berlin')
const utcMeeting =
meetingLocal
.atZone(organizerZone)
.withZoneSameInstant(
ZoneId.of('UTC')
)
console.log(utcMeeting.toString())
const participantZone =
ZoneId.of('Asia/Tokyo')
const participantTime =
utcMeeting.withZoneSameInstant(
participantZone
)
console.log(
participantTime.toString()
)
js-joda-timezone тяжелее обычного Date,
поскольку:
Однако преимущества:
Библиотека содержит типы.
Пример:
import {
ZonedDateTime,
ZoneId
} from '@js-joda/core'
import '@js-joda/timezone'
const zoned: ZonedDateTime =
ZonedDateTime.now(
ZoneId.of('UTC')
)
js-joda-timezone полностью ориентирован на ISO-8601.
Примеры:
2025-05-01T10:00:00Z
2025-05-01T15:00:00+05:00
2025-05-01T15:00:00+05:00[Asia/Almaty]
Пакет особенно важен при работе:
Если приложение:
то может быть достаточно только @js-joda/core.
| Класс | Назначение |
|---|---|
ZoneId |
идентификатор зоны |
ZoneRules |
правила зоны |
ZoneOffset |
фиксированное смещение |
ZonedDateTime |
дата и время с зоной |
Instant |
момент времени UTC |
Instant
↓
ZoneId
↓
ZonedDateTime
↓
Форматирование и отображение
Date;java.time;