Japanese календарь

Библиотека js-joda поддерживает несколько календарных систем, включая японский императорский календарь. Для работы с ним используется модуль @js-joda/locale, содержащий реализацию JapaneseChronology.

Японский календарь отличается от григорианского тем, что годы отсчитываются внутри эпох правления императоров. Каждая эпоха имеет собственное имя и собственный первый год.

Примеры эпох:

Эпоха Начало
Meiji 1868
Taisho 1912
Showa 1926
Heisei 1989
Reiwa 2019

Дата 2020-05-10 в японском календаре соответствует:

Reiwa 2-05-10

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

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

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

Импорт:

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

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

Создание японской даты

Японская дата создаётся через объект хронологии.

const chronology = JapaneseChronology.INSTANCE;

const date = chronology.dateNow();

console.log(date.toString());

Пример результата:

Japanese Reiwa 8-05-25

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

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

const isoDate = LocalDate.of(2024, 4, 15);

const japaneseDate = chronology.date(isoDate);

console.log(japaneseDate.toString());

Результат:

Japanese Reiwa 6-04-15

Работа с эпохами

Эпохи представлены объектами JapaneseEra.

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

const era = japaneseDate.era();

console.log(era.toString());

Результат:

Reiwa

Получение года внутри эпохи

В японском календаре существует различие между:

  • абсолютным годом;
  • годом внутри эпохи.

Получение года эпохи:

const yearOfEra = japaneseDate.get(ChronoField.YEAR_OF_ERA);

console.log(yearOfEra);

Результат:

6

Получение номера эпохи

const eraValue = japaneseDate.get(ChronoField.ERA);

console.log(eraValue);

Создание даты через эпоху

Дата может быть создана напрямую через эпоху и год эпохи.

const {
    JapaneseEra
} = require('@js-joda/locale');

const date = chronology.date(
    JapaneseEra.REIWA,
    3,
    7,
    20
);

console.log(date.toString());

Результат:

Japanese Reiwa 3-07-20

Переход между эпохами

Особенность японского календаря — резкое изменение года при смене императора.

Например:

const lastHeisei = chronology.date(
    2019,
    4,
    30
);

console.log(lastHeisei.toString());

Результат:

Japanese Heisei 31-04-30

Следующий день:

const nextDay = lastHeisei.plusDays(1);

console.log(nextDay.toString());

Результат:

Japanese Reiwa 1-05-01

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

Добавление дней

const date = chronology.date(
    2025,
    1,
    10
);

const result = date.plusDays(20);

console.log(result.toString());

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

const result = date.plusMonths(5);

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

const result = date.plusYears(2);

При добавлении лет библиотека корректно обрабатывает смену эпох.


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

const result = date.minusYears(1);

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

equals

const d1 = chronology.date(2024, 1, 1);
const d2 = chronology.date(2024, 1, 1);

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

isBefore

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

isAfter

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

Преобразование в ISO-дату

Японская дата может быть преобразована обратно в LocalDate.

const iso = LocalDate.from(japaneseDate);

console.log(iso.toString());

Форматирование японских дат

Для форматирования используется DateTimeFormatter.

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

Создание форматтера:

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

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

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

Результат:

Reiwa 6-04-15

Символы форматирования

Символ Значение
G эпоха
y год эпохи
M месяц
d день

Полное имя эпохи

const formatter = DateTimeFormatter.ofPattern(
    'GGGG y年MM月dd日'
);

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

Результат:

令和 6年04月15日

Работа с TemporalField

Японские даты поддерживают стандартные поля времени.

Получение месяца:

const month = japaneseDate.get(
    ChronoField.MONTH_OF_YEAR
);

Получение дня месяца:

const day = japaneseDate.get(
    ChronoField.DAY_OF_MONTH
);

Получение дня года:

const dayOfYear = japaneseDate.get(
    ChronoField.DAY_OF_YEAR
);

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

Метод with создаёт новую дату с изменённым полем.

Изменение года эпохи

const modified = japaneseDate.with(
    ChronoField.YEAR_OF_ERA,
    10
);

console.log(modified.toString());

Изменение месяца

const modified = japaneseDate.with(
    ChronoField.MONTH_OF_YEAR,
    12
);

Immutable-модель

Все объекты js-joda неизменяемы.

Пример:

const original = chronology.date(
    2024,
    1,
    1
);

const modified = original.plusYears(1);

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

Исходный объект останется прежним.


Получение текущей даты

const now = chronology.dateNow();

Получение даты из Clock

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

const clock = Clock.system(
    ZoneId.of('Asia/Tokyo')
);

const now = chronology.dateNow(clock);

JapaneseDate и ChronoLocalDate

Японская дата реализует интерфейс ChronoLocalDate.

Это означает поддержку:

  • сравнения;
  • форматирования;
  • арифметики;
  • преобразований;
  • работы с temporal API.

Смена календарной системы

Одну и ту же дату можно представить в разных календарях.

const isoDate = LocalDate.of(
    2024,
    6,
    1
);

const japanese = chronology.date(isoDate);

console.log(isoDate.toString());
console.log(japanese.toString());

Результат:

2024-06-01
Japanese Reiwa 6-06-01

Поддержка високосных лет

Проверка выполняется автоматически.

const leap = chronology.isLeapYear(2024);

console.log(leap);

Диапазоны поддерживаемых дат

Японский календарь ограничен историческими эпохами.

Попытка создать дату вне диапазона поддерживаемых эпох может привести к ошибке.

const date = chronology.date(
    1800,
    1,
    1
);

JapaneseEra

Основные эпохи:

Константа Эпоха
JapaneseEra.MEIJI Meiji
JapaneseEra.TAISHO Taisho
JapaneseEra.SHOWA Showa
JapaneseEra.HEISEI Heisei
JapaneseEra.REIWA Reiwa

Пример полного сценария

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

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

const chronology = JapaneseChronology.INSTANCE;

const birthday = chronology.date(
    JapaneseEra.HEISEI,
    10,
    3,
    15
);

const formatter = DateTimeFormatter.ofPattern(
    'G y年MM月dd日'
);

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

const nextYear = birthday.plusYears(1);

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

Результат:

Heisei 10年03月15日
Heisei 11年03月15日

Особенности японского календаря в js-joda

1. Эпохи являются частью даты

В отличие от ISO-календаря, японская дата всегда связана с эпохой.


2. Год начинается заново

При смене эпохи год снова становится равным 1.


3. Арифметика работает через ISO-временную шкалу

Несмотря на отображение эпох, вычисления производятся на основе абсолютной временной линии.


4. Форматирование зависит от локали

Отображение эпох может различаться:

  • Reiwa
  • 令和
  • R

Использование локализации

const formatter = DateTimeFormatter
    .ofPattern('GGGG y年MM月dd日');

При подключении локалей возможно отображение японских названий эпох.


Сериализация

В строку

const text = japaneseDate.toString();

Обратно в дату

const parsed = chronology.date(
    LocalDate.parse('2024-04-15')
);

Ошибки при работе с эпохами

Некорректный год эпохи:

chronology.date(
    JapaneseEra.REIWA,
    0,
    1,
    1
);

Первый год эпохи всегда начинается с 1.


Проверка поддерживаемого поля

const supported = japaneseDate.isSupported(
    ChronoField.YEAR_OF_ERA
);

console.log(supported);

Получение диапазона значений

const range = japaneseDate.range(
    ChronoField.DAY_OF_MONTH
);

console.log(range.toString());

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

const start = chronology.date(
    2020,
    1,
    1
);

const end = chronology.date(
    2025,
    1,
    1
);

const years = end.until(start).years();

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

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

const zoned = ZonedDateTime.now(
    ZoneId.of('Asia/Tokyo')
);

const japanese = chronology.date(
    zoned.toLocalDate()
);

Практические сценарии использования

Государственные японские системы

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

Финансовые системы Японии

Многие банковские и бухгалтерские системы используют японские эпохи в отчётности.


Архивные данные

Исторические данные часто сохраняются в формате эпох.


Международные приложения

Глобальные приложения могут отображать даты в локальной культурной форме.