Библиотека js-joda построена модульно. Базовый пакет предоставляет ядро API, повторяющее возможности Java Time API из Java, однако многие дополнительные функции вынесены в отдельные расширения сообщества. Такой подход позволяет подключать только необходимые компоненты без увеличения размера итогового приложения.
Наиболее известные расширения:
@js-joda/timezone@js-joda/locale@js-joda/extra@js-joda/core как базовый фундаментКаждое расширение решает отдельную задачу:
| Расширение | Назначение |
|---|---|
@js-joda/timezone |
Работа с часовыми поясами IANA |
@js-joda/locale |
Локализация форматирования |
@js-joda/extra |
Дополнительные типы дат и времени |
@js-joda/core |
Основной API |
| сторонние плагины | Интеграция с фреймворками и сериализаторами |
Пакет @js-joda/timezone добавляет полноценную поддержку
часовых поясов IANA:
Europe/MoscowAsia/AlmatyAmerica/New_YorkUTCБез этого расширения библиотека умеет работать только с
фиксированными смещениями (+03:00, -05:00), но
не знает правил перехода на летнее и зимнее время.
npm install @js-joda/core
npm install @js-joda/timezone
import '@js-joda/timezone';
После импорта становятся доступны все правила временных зон.
import { ZonedDateTime, ZoneId } from '@js-joda/core';
import '@js-joda/timezone';
const zone = ZoneId.of('Europe/Moscow');
const now = ZonedDateTime.now(zone);
console.log(now.toString());
import {
ZonedDateTime,
ZoneId
} from '@js-joda/core';
import '@js-joda/timezone';
const tokyo = ZoneId.of('Asia/Tokyo');
const berlin = ZoneId.of('Europe/Berlin');
const meeting = ZonedDateTime
.parse('2025-05-10T15:00:00+09:00[Asia/Tokyo]');
const berlinTime = meeting.withZoneSameInstant(berlin);
console.log(berlinTime.toString());
Метод withZoneSameInstant() сохраняет момент времени,
изменяя только представление относительно другого часового пояса.
Одно из главных преимуществ timezone-расширения — корректная работа с DST (Daylight Saving Time).
const zone = ZoneId.of('America/New_York');
const date = ZonedDateTime.parse(
'2025-03-09T01:30:00-05:00[America/New_York]'
);
console.log(date.plusHours(2).toString());
Во время перехода на летнее время некоторые часы могут отсутствовать. Библиотека учитывает это автоматически.
Пакет @js-joda/locale предоставляет локализованное
форматирование:
npm install @js-joda/locale
import '@js-joda/locale_ru';
Некоторые сборки разделяют локали по отдельным пакетам.
import {
LocalDate,
DateTimeFormatter
} from '@js-joda/core';
import '@js-joda/locale_ru';
const date = LocalDate.of(2025, 5, 10);
const formatter = DateTimeFormatter
.ofPattern('d MMMM yyyy');
console.log(
date.format(formatter.locale('ru'))
);
Результат:
10 мая 2025
import '@js-joda/locale_fr';
import '@js-joda/locale_de';
const formatter = DateTimeFormatter
.ofPattern('EEEE, d MMMM yyyy');
console.log(
date.format(formatter.locale('fr'))
);
console.log(
date.format(formatter.locale('de'))
);
Пакет @js-joda/extra содержит дополнительные
temporal-типы, отсутствующие в стандартном Java Time API.
Среди них:
YearQuarterQuarterYearWeekIntervalAmPmDayOfMonthЭто особенно полезно в бизнес-приложениях, аналитике и финансовых системах.
import {
Quarter,
YearQuarter
} from '@js-joda/extra';
const quarter = Quarter.Q2;
console.log(quarter.toString());
const yq = YearQuarter.of(2025, Quarter.Q3);
console.log(yq.toString());
Результат:
2025-Q3
const next = yq.plusQuarters(1);
console.log(next.toString());
Тип Interval описывает промежуток между двумя моментами
времени.
import { Instant } from '@js-joda/core';
import { Interval } from '@js-joda/extra';
const start = Instant.parse('2025-01-01T00:00:00Z');
const end = Instant.parse('2025-02-01T00:00:00Z');
const interval = Interval.of(start, end);
console.log(interval.toString());
const current = Instant.now();
console.log(
interval.contains(current)
);
const another = Interval.parse(
'2025-01-15T00:00:00Z/2025-03-01T00:00:00Z'
);
console.log(
interval.overlaps(another)
);
Многие бизнес-системы используют недельный календарь ISO-8601.
import { YearWeek } from '@js-joda/extra';
const week = YearWeek.of(2025, 20);
console.log(week.toString());
const next = week.plusWeeks(1);
console.log(next.toString());
Расширения можно комбинировать.
import {
ZonedDateTime,
ZoneId,
DateTimeFormatter
} from '@js-joda/core';
import '@js-joda/timezone';
import '@js-joda/locale_ru';
const date = ZonedDateTime.now(
ZoneId.of('Europe/Moscow')
);
const formatter = DateTimeFormatter
.ofPattern('dd MMMM yyyy HH:mm');
console.log(
date.format(
formatter.locale('ru')
)
);
Все community-расширения придерживаются ключевого принципа Js-joda — неизменяемости объектов.
Каждая операция возвращает новый экземпляр:
const original = YearWeek.of(2025, 10);
const updated = original.plusWeeks(2);
console.log(original.toString());
console.log(updated.toString());
Это исключает скрытые мутации и делает работу с датами безопаснее в многокомпонентных приложениях.
Большинство пакетов сообщества полностью поддерживают TypeScript.
import { Interval } from '@js-joda/extra';
const interval: Interval = Interval.parse(
'2025-01-01T00:00:00Z/2025-02-01T00:00:00Z'
);
Расширения сохраняют преимущества строгой temporal-модели:
LocalDate и
Instantconst quarter = YearQuarter.now();
const reportQuarter = quarter.minusQuarters(1);
const currentWeek = YearWeek.now();
const previousWeek = currentWeek.minusWeeks(1);
const booking = Interval.parse(
'2025-05-10T10:00:00Z/2025-05-10T12:00:00Z'
);
Расширения Js-joda ориентированы на:
DateОсобенно заметны преимущества при:
Пакеты сообщества проектировались с учётом современных сборщиков:
Подключаются только реально используемые части API.
import { YearQuarter } from '@js-joda/extra';
Пакет timezone содержит базу IANA, что увеличивает размер bundle.
Для frontend-приложений это может быть критично.
Некоторые локали могут поддерживаться не полностью:
Расширения должны соответствовать версии
@js-joda/core.
Например:
@js-joda/core 5.x
@js-joda/timezone 5.x
Несовместимые версии могут вызывать ошибки runtime.
Часто создаётся отдельный слой работы с датами:
src/
├── temporal/
│ ├── formatter.js
│ ├── timezone.js
│ ├── intervals.js
│ └── quarters.js
Это упрощает:
Community-расширения Js-joda отличаются от экосистемы Moment.js несколькими особенностями:
| Js-joda | Moment.js |
|---|---|
| immutable API | mutable API |
| строгая temporal-модель | единый объект даты |
| Java Time архитектура | собственная архитектура |
| типобезопасность | высокая вероятность смешения типов |
| модульные расширения | глобальные плагины |
Библиотека Luxon уже содержит timezone и locale-функции внутри ядра, тогда как Js-joda выносит их в отдельные пакеты.
Преимущества подхода Js-joda:
Архитектура библиотеки допускает создание собственных temporal-утилит.
Пример helper-модуля:
import { YearQuarter } from '@js-joda/extra';
export function currentFiscalQuarter(offset = 0) {
return YearQuarter.now()
.plusQuarters(offset);
}
Во многих проектах создаются дополнительные обёртки:
export function formatRussianDate(date) {
return date.format(
DateTimeFormatter
.ofPattern('dd.MM.yyyy')
.locale('ru')
);
}
test('timezone conversion', () => {
const moscow = ZoneId.of('Europe/Moscow');
const utc = ZoneId.of('UTC');
const date = ZonedDateTime.now(moscow);
expect(
date.withZoneSameInstant(utc)
).toBeDefined();
});
test('interval overlap', () => {
const a = Interval.parse(
'2025-01-01T00:00:00Z/2025-01-10T00:00:00Z'
);
const b = Interval.parse(
'2025-01-05T00:00:00Z/2025-01-20T00:00:00Z'
);
expect(a.overlaps(b)).toBe(true);
});
В Domain-Driven Design расширения Js-joda особенно удобны благодаря специализированным temporal-типам.
Пример:
class BillingPeriod {
constructor(interval) {
this.interval = interval;
}
}
Вместо строковых дат используются строгие temporal-объекты.
Community-пакеты превращают Js-joda в полноцененную платформу для работы со временем:
Именно расширяемость делает экосистему Js-joda особенно востребованной в: