Китайский календарь

В Intl календарная система является частью более широкой модели локализации дат и времени. Базовая точка входа — Intl.DateTimeFormat, где календарь задаётся через опцию calendar. Это позволяет форматировать одну и ту же дату в разных календарных системах без ручных преобразований.

const dtf = new Intl.DateTimeFormat('ru', {
  calendar: 'chinese',
  dateStyle: 'full'
});

dtf.format(new Date());

Календарь chinese относится к лунно-солнечным календарным системам и отличается от григорианского не только отображением, но и логикой вычисления года, месяца и цикла.


Китайский календарь в контексте ECMAScript

Китайский календарь — это традиционная система летоисчисления, основанная на сочетании лунных месяцев и солнечных корректировок. В JavaScript он представлен как один из стандартных идентификаторов календарей ICU (chinese).

В рамках Intl он не требует ручной реализации астрономии или вычислений циклов: движок использует ICU (International Components for Unicode), где уже реализована вся логика преобразования дат.

Ключевая особенность: одна и та же григорианская дата может соответствовать разным значениям года/месяца/дня в китайской системе.


Использование календаря через Intl.DateTimeFormat

Базовое форматирование

const formatter = new Intl.DateTimeFormat('zh-Hans', {
  calendar: 'chinese',
  year: 'numeric',
  month: 'long',
  day: 'numeric'
});

formatter.format(new Date());

Здесь локаль zh-Hans усиливает соответствие культурному контексту, но сам календарь задаётся отдельно.


Форматирование с разными стилями

const short = new Intl.DateTimeFormat('ru', {
  calendar: 'chinese',
  dateStyle: 'short'
});

const full = new Intl.DateTimeFormat('ru', {
  calendar: 'chinese',
  dateStyle: 'full'
});

dateStyle влияет только на представление, но не на календарную систему.


Разница между григорианским и китайским календарём

Григорианский календарь (gregory) в Intl — это стандарт по умолчанию. Он линейный и основан на солнечном цикле.

Китайский календарь (chinese) является циклическим и включает:

  • лунные месяцы
  • вставочные (эмболисмические) месяцы
  • 60-летний цикл стволов и ветвей (干支)
  • параллельное существование «внутреннего года» и сезонной коррекции

В результате:

new Intl.DateTimeFormat('en', { calendar: 'gregory' }).format(new Date());
new Intl.DateTimeFormat('en', { calendar: 'chinese' }).format(new Date());

выведут разные структурные представления одной и той же даты.


formatToParts и структура китайской даты

Метод formatToParts позволяет получить не строку, а структурированное представление.

const parts = new Intl.DateTimeFormat('en', {
  calendar: 'chinese',
  year: 'numeric',
  month: 'numeric',
  day: 'numeric'
}).formatToParts(new Date());

Результат содержит компоненты:

  • year
  • month
  • day
  • literal

Особенность китайского календаря в том, что year может отражать циклическое значение, а не привычный линейный год.


Использование в Intl.Locale

Календарь может быть частью описания локали через Intl.Locale:

const locale = new Intl.Locale('zh-CN', {
  calendar: 'chinese'
});

locale.calendar;

Это важно при построении интерфейсов, где локаль передаётся как объект конфигурации, а не строка.


Поддерживаемые значения календарей

Список доступных календарей можно получить через:

Intl.supportedValuesOf('calendar');

Среди стандартных значений обычно присутствуют:

  • gregory
  • chinese
  • japanese
  • islamic
  • hebrew
  • buddhist

Наличие chinese означает поддержку лунно-солнечной модели ICU, используемой в международной локализации.


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

При использовании calendar: 'chinese' важно учитывать несколько особенностей поведения:

1. Нелинейность года

Год не совпадает с григорианским. Он определяется циклом и может «перекрывать» границы привычного года.

2. Месяцы не фиксированы

Месяцы зависят от лунных фаз, поэтому их длина варьируется.

3. Вставочные месяцы

Некоторые годы содержат дополнительный месяц, который не имеет прямого аналога в григорианской системе.


Практика форматирования дат

Базовый пример отображения

const d = new Date(2026, 0, 1);

const fmt = new Intl.DateTimeFormat('zh-Hans', {
  calendar: 'chinese',
  year: 'numeric',
  month: 'long',
  day: 'numeric'
});

fmt.format(d);

Комбинация с локализацией языка

new Intl.DateTimeFormat('zh-Hans', {
  calendar: 'chinese',
  weekday: 'long',
  year: 'numeric',
  month: 'long',
  day: 'numeric'
}).format(new Date());

Локаль влияет на язык названий месяцев и дней недели, но не на календарную логику.


Поведение при разных локалях

const date = new Date();

new Intl.DateTimeFormat('en', { calendar: 'chinese' }).format(date);
new Intl.DateTimeFormat('ru', { calendar: 'chinese' }).format(date);
new Intl.DateTimeFormat('zh-Hans', { calendar: 'chinese' }).format(date);

Различия проявляются в:

  • языке вывода
  • порядке компонентов
  • форматировании чисел
  • стиле разделителей

Взаимодействие с другими опциями DateTimeFormat

Китайский календарь совместим со всеми основными опциями:

  • year
  • month
  • day
  • weekday
  • hour, minute, second
  • timeZone
new Intl.DateTimeFormat('zh-Hans', {
  calendar: 'chinese',
  year: 'numeric',
  month: '2-digit',
  day: '2-digit',
  hour: '2-digit',
  minute: '2-digit',
  timeZone: 'Asia/Shanghai'
}).format(new Date());

Тонкости интерпретации даты

Intl не изменяет исходный объект Date. Он всегда хранит время в формате Unix timestamp. Календарная система применяется только на этапе форматирования.

Это означает:

  • нельзя «создать китайскую дату» как отдельный объект Date
  • нельзя выполнять арифметику дат в китайской системе через стандартный Date
  • преобразование происходит только при выводе

Ограничения модели

Календарь chinese в Intl имеет ряд архитектурных ограничений:

  • отсутствует прямой API для получения «структуры китайской даты» без форматирования
  • нет обратного преобразования строки в китайскую дату через Intl
  • нет доступа к внутренним циклам (например, стволы/ветви) через стандартные методы

Вся работа идёт через ICU-слой форматирования.


Сравнение с другими календарями ICU

В рамках Intl китайский календарь отличается от других систем:

  • gregory — линейная солнечная модель
  • islamic — лунный календарь с религиозной привязкой
  • hebrew — лунно-солнечный календарь с фиксированными правилами вставок
  • chinese — циклический лунно-солнечный календарь с 60-летним циклом

Ключевое отличие chinese — наличие циклической нумерации лет, не являющейся просто счётом от фиксированной точки.


Поведение в разных движках

Поддержка calendar: 'chinese' зависит от ICU версии внутри среды выполнения:

  • Node.js использует ICU из сборки
  • браузеры используют системные ICU-библиотеки или встроенные версии
  • поведение может отличаться в деталях форматирования

При разработке интерфейсов с критичной локализацией это учитывается через feature detection:

Intl.supportedValuesOf('calendar').includes('chinese');