Библиотека 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-дату.
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);
const d1 = chronology.date(2024, 1, 1);
const d2 = chronology.date(2024, 1, 1);
console.log(d1.equals(d2));
console.log(d1.isBefore(d2));
console.log(d1.isAfter(d2));
Японская дата может быть преобразована обратно в
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日
Японские даты поддерживают стандартные поля времени.
Получение месяца:
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 создаёт новую дату с изменённым полем.
const modified = japaneseDate.with(
ChronoField.YEAR_OF_ERA,
10
);
console.log(modified.toString());
const modified = japaneseDate.with(
ChronoField.MONTH_OF_YEAR,
12
);
Все объекты 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();
const {
Clock,
ZoneId
} = require('@js-joda/core');
const clock = Clock.system(
ZoneId.of('Asia/Tokyo')
);
const now = chronology.dateNow(clock);
Японская дата реализует интерфейс ChronoLocalDate.
Это означает поддержку:
Одну и ту же дату можно представить в разных календарях.
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.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日
В отличие от ISO-календаря, японская дата всегда связана с эпохой.
При смене эпохи год снова становится равным 1.
Несмотря на отображение эпох, вычисления производятся на основе абсолютной временной линии.
Отображение эпох может различаться:
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();
const {
ZonedDateTime,
ZoneId
} = require('@js-joda/core');
const zoned = ZonedDateTime.now(
ZoneId.of('Asia/Tokyo')
);
const japanese = chronology.date(
zoned.toLocalDate()
);
Многие банковские и бухгалтерские системы используют японские эпохи в отчётности.
Исторические данные часто сохраняются в формате эпох.
Глобальные приложения могут отображать даты в локальной культурной форме.