Расширения сообщества

Библиотека js-joda построена модульно. Базовый пакет предоставляет ядро API, повторяющее возможности Java Time API из Java, однако многие дополнительные функции вынесены в отдельные расширения сообщества. Такой подход позволяет подключать только необходимые компоненты без увеличения размера итогового приложения.

Наиболее известные расширения:

  • @js-joda/timezone
  • @js-joda/locale
  • @js-joda/extra
  • @js-joda/core как базовый фундамент
  • интеграционные пакеты для TypeScript, сериализации и форматирования

Каждое расширение решает отдельную задачу:

Расширение Назначение
@js-joda/timezone Работа с часовыми поясами IANA
@js-joda/locale Локализация форматирования
@js-joda/extra Дополнительные типы дат и времени
@js-joda/core Основной API
сторонние плагины Интеграция с фреймворками и сериализаторами

Расширение timezone

Назначение

Пакет @js-joda/timezone добавляет полноценную поддержку часовых поясов IANA:

  • Europe/Moscow
  • Asia/Almaty
  • America/New_York
  • UTC

Без этого расширения библиотека умеет работать только с фиксированными смещениями (+03:00, -05:00), но не знает правил перехода на летнее и зимнее время.


Установка

npm install @js-joda/core
npm install @js-joda/timezone

Подключение

import '@js-joda/timezone';

После импорта становятся доступны все правила временных зон.


Работа с ZonedDateTime

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() сохраняет момент времени, изменяя только представление относительно другого часового пояса.


DST и переходы времени

Одно из главных преимуществ 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());

Во время перехода на летнее время некоторые часы могут отсутствовать. Библиотека учитывает это автоматически.


Расширение locale

Назначение

Пакет @js-joda/locale предоставляет локализованное форматирование:

  • месяцы на разных языках
  • локализованные дни недели
  • региональные форматы даты
  • поддержку CLDR-локалей

Установка

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'))
);

Расширение extra

Назначение

Пакет @js-joda/extra содержит дополнительные temporal-типы, отсутствующие в стандартном Java Time API.

Среди них:

  • YearQuarter
  • Quarter
  • YearWeek
  • Interval
  • AmPm
  • DayOfMonth

Это особенно полезно в бизнес-приложениях, аналитике и финансовых системах.


Quarter и YearQuarter

Работа с кварталами

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

Интервалы времени

Тип 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)
);

YearWeek

ISO-нумерация недель

Многие бизнес-системы используют недельный календарь 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());

Интеграция расширений

Совместное использование timezone и locale

Расширения можно комбинировать.

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')
    )
);

Расширение immutable-архитектуры

Все community-расширения придерживаются ключевого принципа Js-joda — неизменяемости объектов.

Каждая операция возвращает новый экземпляр:

const original = YearWeek.of(2025, 10);

const updated = original.plusWeeks(2);

console.log(original.toString());
console.log(updated.toString());

Это исключает скрытые мутации и делает работу с датами безопаснее в многокомпонентных приложениях.


Интеграция с TypeScript

Типизация расширений

Большинство пакетов сообщества полностью поддерживают TypeScript.

import { Interval } from '@js-joda/extra';

const interval: Interval = Interval.parse(
    '2025-01-01T00:00:00Z/2025-02-01T00:00:00Z'
);

Строгая проверка типов

Расширения сохраняют преимущества строгой temporal-модели:

  • нельзя случайно смешать LocalDate и Instant
  • интервалы работают только с корректными temporal-типами
  • исключены неявные преобразования

Использование в аналитических системах

Финансовые кварталы

const 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
  • функциональный стиль работы с temporal-объектами

Особенно заметны преимущества при:

  • серверных вычислениях
  • обработке временных рядов
  • финансовых операциях
  • календарных системах
  • распределённых приложениях

Tree shaking и модульность

Пакеты сообщества проектировались с учётом современных сборщиков:

  • Webpack
  • Rollup
  • Vite
  • esbuild

Подключаются только реально используемые части API.

import { YearQuarter } from '@js-joda/extra';

Ограничения community-расширений

Размер timezone-базы

Пакет timezone содержит базу IANA, что увеличивает размер bundle.

Для frontend-приложений это может быть критично.


Частичная локализация

Некоторые локали могут поддерживаться не полностью:

  • отсутствующие шаблоны
  • сокращённые формы месяцев
  • нестандартные региональные настройки

Различия версий

Расширения должны соответствовать версии @js-joda/core.

Например:

@js-joda/core 5.x
@js-joda/timezone 5.x

Несовместимые версии могут вызывать ошибки runtime.


Практика организации проекта

Выделение temporal-модуля

Часто создаётся отдельный слой работы с датами:

src/
 ├── temporal/
 │    ├── formatter.js
 │    ├── timezone.js
 │    ├── intervals.js
 │    └── quarters.js

Это упрощает:

  • миграции
  • тестирование
  • замену библиотек
  • централизованную настройку локалей

Сравнение с Moment.js-плагинами

Community-расширения Js-joda отличаются от экосистемы Moment.js несколькими особенностями:

Js-joda Moment.js
immutable API mutable API
строгая temporal-модель единый объект даты
Java Time архитектура собственная архитектура
типобезопасность высокая вероятность смешения типов
модульные расширения глобальные плагины

Сравнение с Luxon

Библиотека Luxon уже содержит timezone и locale-функции внутри ядра, тогда как Js-joda выносит их в отдельные пакеты.

Преимущества подхода Js-joda:

  • меньший базовый размер
  • независимые обновления модулей
  • возможность тонкой оптимизации bundle

Пользовательские расширения

Архитектура библиотеки допускает создание собственных temporal-утилит.

Пример helper-модуля:

import { YearQuarter } from '@js-joda/extra';

export function currentFiscalQuarter(offset = 0) {
    return YearQuarter.now()
        .plusQuarters(offset);
}

Расширение formatter-утилит

Во многих проектах создаются дополнительные обёртки:

export function formatRussianDate(date) {
    return date.format(
        DateTimeFormatter
            .ofPattern('dd.MM.yyyy')
            .locale('ru')
    );
}

Подходы к тестированию расширений

Проверка timezone-логики

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);
});

Расширения и DDD

В Domain-Driven Design расширения Js-joda особенно удобны благодаря специализированным temporal-типам.

Пример:

class BillingPeriod {
    constructor(interval) {
        this.interval = interval;
    }
}

Вместо строковых дат используются строгие temporal-объекты.


Роль расширений в enterprise-разработке

Community-пакеты превращают Js-joda в полноцененную платформу для работы со временем:

  • timezone-вычисления
  • ISO-календари
  • финансовые кварталы
  • интервалы
  • локализованное форматирование
  • типобезопасная temporal-модель
  • поддержка сложных бизнес-календарей

Именно расширяемость делает экосистему Js-joda особенно востребованной в:

  • банковских системах
  • ERP-платформах
  • аналитических сервисах
  • системах бронирования
  • международных web-приложениях
  • высоконагруженных backend-сервисах