Minguo и ThaiBuddhist календари

Библиотека Js-joda предоставляет реализацию различных календарных систем, совместимых со спецификацией Java Time API. Помимо стандартного ISO-календаря доступны исторические и национальные календарные системы, включая календарь Миньго (Minguo) и тайский буддийский календарь (ThaiBuddhist).

Поддержка альтернативных календарей реализована через модуль @js-joda/locale, который включает классы хронологий (Chronology) и специализированные типы дат.

Подключение модулей

Для работы с альтернативными календарями требуется установка дополнительных пакетов:

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

Импорт:

const {
    LocalDate,
    ChronoField
} = require('@js-joda/core');

const {
    MinguoChronology,
    ThaiBuddhistChronology
} = require('@js-joda/locale');

Концепция хронологий

В Js-joda любая календарная система реализуется через объект Chronology.

Основные задачи хронологии:

  • создание дат;
  • преобразование между календарями;
  • вычисление эпох;
  • управление правилами летоисчисления;
  • поддержка локализованного форматирования.

ISO-календарь используется по умолчанию, однако альтернативные календари сохраняют совместимость с базовыми временными API.


Календарь Minguo

История календаря

Календарь Миньго используется на Тайване и связан с основанием Китайской Республики.

Особенности:

  • год 1 соответствует 1912 году ISO;
  • годы до 1912 считаются годами «до республики»;
  • месяцы и дни совпадают с григорианским календарём;
  • изменяется только система отсчёта лет.

Соответствие годов:

Minguo ISO
1 1912
10 1921
100 2011
112 2023

Создание дат Minguo

Создание через chronology

const chronology = MinguoChronology.INSTANCE;

const date = chronology.date(112, 5, 20);

console.log(date.toString());

Результат:

Minguo ROC 112-05-20

Здесь:

  • ROC — Republic of China;
  • 112 — год календаря Миньго;
  • 05 — месяц;
  • 20 — день.

Создание из ISO-даты

const isoDate = LocalDate.of(2023, 5, 20);

const minguoDate = MinguoChronology.INSTANCE.date(isoDate);

console.log(minguoDate.toString());

Результат:

Minguo ROC 112-05-20

Получение компонентов даты

Извлечение года

const date = MinguoChronology.INSTANCE.date(112, 8, 15);

console.log(date.year());

Результат:

112

Извлечение месяца и дня

console.log(date.monthValue());
console.log(date.dayOfMonth());

Результат:

8
15

Работа с ChronoField

Тип ChronoField позволяет получать универсальные значения независимо от календарной системы.

Получение proleptic year

const year = date.get(ChronoField.YEAR);

console.log(year);

Получение эпохи

const era = date.get(ChronoField.ERA);

console.log(era);

В календаре Миньго:

  • 1 — ROC;
  • 0 — BEFORE_ROC.

Эпохи Minguo

Работа с датами до основания республики

const oldDate = MinguoChronology.INSTANCE.date(-5, 3, 10);

console.log(oldDate.toString());

Результат:

Minguo BEFORE_ROC 6-03-10

Отрицательные годы автоматически переводятся в эпоху BEFORE_ROC.


Проверка эпохи

if (oldDate.era().toString() === 'BEFORE_ROC') {
    console.log('Дата до основания республики');
}

Арифметика дат

Все стандартные операции доступны и для альтернативных календарей.

Добавление лет

const date = MinguoChronology.INSTANCE.date(112, 1, 1);

const next = date.plusYears(5);

console.log(next.toString());

Результат:

Minguo ROC 117-01-01

Добавление месяцев

const result = date.plusMonths(8);

console.log(result.toString());

Вычитание дней

const result = date.minusDays(30);

console.log(result.toString());

Сравнение дат

equals

const d1 = MinguoChronology.INSTANCE.date(112, 5, 1);
const d2 = MinguoChronology.INSTANCE.date(112, 5, 1);

console.log(d1.equals(d2));

isBefore и isAfter

const d1 = MinguoChronology.INSTANCE.date(110, 1, 1);
const d2 = MinguoChronology.INSTANCE.date(112, 1, 1);

console.log(d1.isBefore(d2));
console.log(d2.isAfter(d1));

Преобразование в ISO

Получение LocalDate

const minguo = MinguoChronology.INSTANCE.date(112, 5, 20);

const iso = LocalDate.from(minguo);

console.log(iso.toString());

Результат:

2023-05-20

ThaiBuddhist календарь

Особенности тайского буддийского календаря

Тайский буддийский календарь широко используется в Таиланде.

Главная особенность:

  • год больше ISO на 543.

Примеры:

Thai Buddhist ISO
2566 2023
2567 2024
2500 1957

Месяцы и дни совпадают с григорианским календарём.


Создание ThaiBuddhist дат

Создание через chronology

const thai = ThaiBuddhistChronology.INSTANCE;

const date = thai.date(2566, 7, 15);

console.log(date.toString());

Результат:

ThaiBuddhist BE 2566-07-15

Создание из ISO

const isoDate = LocalDate.of(2023, 7, 15);

const thaiDate =
    ThaiBuddhistChronology.INSTANCE.date(isoDate);

console.log(thaiDate.toString());

Эпохи ThaiBuddhist

Доступные эпохи

В тайском календаре используются:

  • BE — Buddhist Era;
  • BEFORE_BE.

Создание даты до буддийской эры

const ancient =
    ThaiBuddhistChronology.INSTANCE.date(-10, 1, 1);

console.log(ancient.toString());

Получение компонентов ThaiBuddhist даты

Год

console.log(date.year());

День года

console.log(date.dayOfYear());

День недели

console.log(date.dayOfWeek().toString());

Конвертация ThaiBuddhist в ISO

const thaiDate =
    ThaiBuddhistChronology.INSTANCE.date(2566, 1, 1);

const iso = LocalDate.from(thaiDate);

console.log(iso.toString());

Результат:

2023-01-01

Преобразование между Minguo и ThaiBuddhist

Напрямую календари не конвертируются. Используется ISO-представление как промежуточный формат.

Пример преобразования

const minguo =
    MinguoChronology.INSTANCE.date(112, 5, 20);

const iso =
    LocalDate.from(minguo);

const thai =
    ThaiBuddhistChronology.INSTANCE.date(iso);

console.log(thai.toString());

Результат:

ThaiBuddhist BE 2566-05-20

Использование temporal API

Альтернативные календари поддерживают интерфейс TemporalAccessor.

Получение значения поля

const thai =
    ThaiBuddhistChronology.INSTANCE.date(2566, 8, 12);

console.log(
    thai.getLong(ChronoField.YEAR)
);

Проверка високосного года

Minguo

const leap =
    MinguoChronology.INSTANCE.isLeapYear(112);

console.log(leap);

ThaiBuddhist

const leap =
    ThaiBuddhistChronology.INSTANCE.isLeapYear(2567);

console.log(leap);

Поскольку оба календаря основаны на ISO-системе, правила високосных лет совпадают с григорианским календарём.


Работа с периодами

Вычисление разницы между датами

const start =
    ThaiBuddhistChronology.INSTANCE.date(2565, 1, 1);

const end =
    ThaiBuddhistChronology.INSTANCE.date(2566, 1, 1);

const days =
    end.toEpochDay() - start.toEpochDay();

console.log(days);

Использование epoch day

Внутренне все альтернативные календари используют epoch day — количество дней от UNIX-эпохи.

Пример

const thai =
    ThaiBuddhistChronology.INSTANCE.date(2566, 6, 1);

console.log(thai.toEpochDay());

Это обеспечивает:

  • совместимость календарей;
  • единые алгоритмы вычислений;
  • корректное сравнение дат;
  • универсальную арифметику.

Форматирование дат

Для форматирования используются стандартные механизмы Js-joda.

Пример

const {
    DateTimeFormatter
} = require('@js-joda/core');

const thai =
    ThaiBuddhistChronology.INSTANCE.date(2566, 5, 10);

const formatter =
    DateTimeFormatter.ofPattern('yyyy-MM-dd');

console.log(
    formatter.format(thai)
);

Типичные сценарии использования

Национальные государственные системы

Календарь Миньго применяется:

  • в официальных документах Тайваня;
  • государственных регистрах;
  • банковских системах;
  • юридических документах.

Тайский буддийский календарь

Используется:

  • в документах Таиланда;
  • системах бронирования;
  • локализованных интерфейсах;
  • государственных сервисах.

Ограничения альтернативных календарей

Не все библиотеки поддерживают chronology

Некоторые внешние инструменты работают только с ISO-датами.

В таких случаях используется преобразование:

const iso = LocalDate.from(customDate);

Возможные ошибки сериализации

JSON-сериализация часто теряет информацию о календарной системе.

Пример:

JSON.stringify(date.toString());

После десериализации требуется повторное создание объекта через соответствующую chronology.


Практический пример: хранение локализованных дат

function createTaiwanDocumentDate() {
    return MinguoChronology.INSTANCE.dateNow();
}

const documentDate =
    createTaiwanDocumentDate();

console.log(documentDate.toString());

Практический пример: международная система

function normalizeDate(date) {
    return LocalDate.from(date);
}

const thai =
    ThaiBuddhistChronology.INSTANCE.date(2566, 3, 15);

const normalized =
    normalizeDate(thai);

console.log(normalized.toString());

Архитектура альтернативных календарей

Все календарные системы Js-joda строятся вокруг общей модели:

  • Chronology
  • ChronoLocalDate
  • Era
  • ChronoField

Это позволяет:

  • использовать единый API;
  • унифицировать вычисления;
  • переключать календарные системы без переписывания бизнес-логики;
  • поддерживать локализацию дат на уровне доменной модели.

Сравнение календарей

Характеристика ISO Minguo ThaiBuddhist
Основа Григорианский Григорианский Григорианский
Смещение лет 0 -1911 +543
Эпохи BCE/CE BEFORE_ROC/ROC BEFORE_BE/BE
Месяцы Совпадают Совпадают Совпадают
Дни Совпадают Совпадают Совпадают

Рекомендации по проектированию

Хранение данных

Для баз данных рекомендуется:

  • хранить даты в ISO;
  • отображать через нужную chronology;
  • не хранить строковые представления альтернативных календарей.

Работа с API

Во внешних API желательно передавать:

LocalDate

а локализованное представление строить только на клиентской стороне.


Использование chronology как слоя представления

Наиболее надёжный подход:

  • бизнес-логика работает с ISO;
  • chronology применяется только для отображения;
  • внутренние вычисления выполняются в стандартном календаре.

Это снижает вероятность ошибок при интеграции с внешними сервисами и базами данных.