Другие календарные системы

Библиотека Luxon использует возможности стандарта Intl и API интернационализации JavaScript для работы с различными календарными системами. Это особенно важно при разработке международных приложений, где даты должны отображаться в привычном для пользователя формате.

Под календарной системой понимается способ представления даты: структура месяцев, недель, лет и эпох. В большинстве приложений используется григорианский календарь, однако в ряде стран и культур применяются альтернативные системы:

  • исламский календарь;
  • буддийский календарь;
  • японский императорский календарь;
  • персидский календарь;
  • китайский календарь;
  • еврейский календарь.

Luxon не реализует календари самостоятельно — библиотека опирается на Intl.DateTimeFormat, поэтому доступность конкретных календарей зависит от среды выполнения и поддержки ICU.


Использование параметра outputCalendar

Основной механизм выбора календарной системы — свойство outputCalendar.

import { DateTime } from "luxon";

const date = DateTime.now().reconfigure({
  outputCalendar: "islamic"
});

console.log(date.toLocaleString());

Метод reconfigure() создаёт новый объект DateTime с изменёнными параметрами локализации.

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

Наиболее распространённые идентификаторы календарей:

Календарь Значение
Григорианский gregory
Исламский islamic
Буддийский buddhist
Японский japanese
Персидский persian
Китайский chinese
Еврейский hebrew
Индийский indian

Исламский календарь

Исламский календарь основан на лунных циклах и содержит 12 лунных месяцев.

const date = DateTime.now().reconfigure({
  locale: "ar",
  outputCalendar: "islamic"
});

console.log(
  date.toLocaleString(DateTime.DATE_FULL)
);

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

١٢ رمضان ١٤٤٧ هـ

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

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

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

outputCalendar: "islamic-umalqura"

или:

outputCalendar: "islamic-civil"

Поддержка зависит от реализации Intl.


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

Буддийский календарь широко используется в Таиланде. Основное отличие — смещение лет относительно григорианского календаря.

const date = DateTime.now().reconfigure({
  locale: "th",
  outputCalendar: "buddhist"
});

console.log(
  date.toLocaleString(DateTime.DATE_FULL)
);

Пример:

24 พฤษภาคม 2569

Смещение лет

Буддийский календарь опережает григорианский на 543 года.

const gregorian = DateTime.now();

const buddhist = gregorian.reconfigure({
  outputCalendar: "buddhist"
});

console.log(gregorian.year);
console.log(buddhist.year);

Важно учитывать, что внутреннее хранение даты в Luxon остаётся неизменным. Меняется только отображение.


Японский императорский календарь

Японский календарь использует эпохи правления императоров.

const date = DateTime.now().reconfigure({
  locale: "ja",
  outputCalendar: "japanese"
});

console.log(
  date.toLocaleString(DateTime.DATE_FULL)
);

Пример вывода:

令和8年5月24日

Эпохи

Каждая эпоха начинается с нового императора:

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

При форматировании Intl автоматически определяет текущую эпоху.


Персидский календарь

Персидский календарь используется в Иране и Афганистане.

const date = DateTime.now().reconfigure({
  locale: "fa",
  outputCalendar: "persian"
});

console.log(
  date.toLocaleString(DateTime.DATE_FULL)
);

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

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

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

Китайский календарь сочетает солнечные и лунные циклы.

const date = DateTime.now().reconfigure({
  locale: "zh",
  outputCalendar: "chinese"
});

console.log(
  date.toLocaleString(DateTime.DATE_FULL)
);

Поддержка китайского календаря может различаться между браузерами и версиями Node.js.


Еврейский календарь

Еврейский календарь применяется в религиозных и культурных системах Израиля.

const date = DateTime.now().reconfigure({
  locale: "he",
  outputCalendar: "hebrew"
});

console.log(
  date.toLocaleString(DateTime.DATE_FULL)
);

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

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

Использование locale и outputCalendar одновременно

Календарь и локаль — разные параметры.

const date = DateTime.now().reconfigure({
  locale: "en",
  outputCalendar: "persian"
});

В этом случае:

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

Результат может выглядеть так:

Ordibehesht 4, 1405 AP

Формирование даты через locale

Иногда календарь можно указать прямо в локали через Unicode Extension.

const date = DateTime.now().setLocale(
  "th-TH-u-ca-buddhist"
);

console.log(
  date.toLocaleString(DateTime.DATE_FULL)
);

Здесь:

  • u — Unicode extension;
  • ca — calendar;
  • buddhist — выбранный календарь.

Разница между внутренней датой и отображением

Luxon всегда хранит дату как абсолютный момент времени.

const now = DateTime.now();

При использовании альтернативного календаря меняется только визуальное представление.

const islamic = now.reconfigure({
  outputCalendar: "islamic"
});

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

  • timestamp остаётся тем же;
  • арифметика дат не меняется;
  • сравнение работает одинаково;
  • timezone не зависит от календаря.

Проверка календаря

Получить активный календарь можно через resolvedLocaleOptions().

const date = DateTime.now().reconfigure({
  outputCalendar: "hebrew"
});

console.log(
  date.resolvedLocaleOptions()
);

Результат:

{
  locale: "en-US",
  numberingSystem: "latn",
  outputCalendar: "hebrew"
}

Numbering System и календари

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

const date = DateTime.now().reconfigure({
  locale: "ar",
  outputCalendar: "islamic",
  numberingSystem: "arab"
});

console.log(
  date.toLocaleString(DateTime.DATE_FULL)
);

Популярные системы счисления

Система Значение
Латинская latn
Арабская arab
Деванагари deva
Тайская thai

Форматирование через toLocaleString

Календари особенно полезны вместе с локализованным форматированием.

date.toLocaleString(DateTime.DATE_FULL);
date.toLocaleString(DateTime.DATETIME_FULL);
date.toLocaleString(DateTime.DATE_HUGE);

Пример:

const date = DateTime.now().reconfigure({
  locale: "ja",
  outputCalendar: "japanese"
});

console.log(
  date.toLocaleString(DateTime.DATE_HUGE)
);

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

Метод toFormat() работает иначе.

date.toFormat("yyyy LLL dd");

Важно понимать, что toFormat() не всегда полностью учитывает альтернативные календарные системы, поскольку использует токены Luxon, а не Intl.DateTimeFormat.

Наиболее корректная локализация достигается через:

toLocaleString()

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

Зависимость от среды выполнения

Поддержка календарей определяется:

  • браузером;
  • версией ICU;
  • Node.js;
  • операционной системой.

Например, старые версии Node.js могут поддерживать только часть календарей.


Ограниченная поддержка в Node.js

Некоторые сборки Node.js используют минимальный ICU.

Проверка:

console.log(
  Intl.supportedValuesOf("calendar")
);

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

[
  "gregory",
  "buddhist",
  "japanese",
  "islamic"
]

Различия между браузерами

Поддержка может отличаться:

Браузер Особенности
Chrome Наиболее полная поддержка
Firefox Хорошая совместимость
Safari Возможны ограничения
Старые браузеры Частичная поддержка

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

Перед использованием календаря желательно проверять его наличие.

function supportsCalendar(calendar) {
  return Intl.supportedValuesOf("calendar")
    .includes(calendar);
}

console.log(
  supportsCalendar("persian")
);

Создание универсального форматтера

function formatDate(date, locale, calendar) {
  return date
    .reconfigure({
      locale,
      outputCalendar: calendar
    })
    .toLocaleString(DateTime.DATE_FULL);
}

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

const now = DateTime.now();

console.log(
  formatDate(now, "ar", "islamic")
);

console.log(
  formatDate(now, "ja", "japanese")
);

console.log(
  formatDate(now, "th", "buddhist")
);

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

Календарная система не влияет на timezone.

const date = DateTime.now()
  .setZone("Asia/Almaty")
  .reconfigure({
    outputCalendar: "persian"
  });

console.log(
  date.toLocaleString(DateTime.DATETIME_FULL)
);

Здесь одновременно используются:

  • часовой пояс;
  • локализация;
  • альтернативный календарь.

Сериализация и календари

ISO-формат всегда остаётся григорианским.

const date = DateTime.now().reconfigure({
  outputCalendar: "buddhist"
});

console.log(date.toISO());

Пример:

2026-05-24T14:20:00.000+06:00

Даже при использовании другого календаря toISO() возвращает стандартную ISO-дату.


Intl.DateTimeFormat и Luxon

Luxon фактически выступает удобной оболочкой над Intl.

Прямой аналог:

new Intl.DateTimeFormat("ja-JP-u-ca-japanese", {
  dateStyle: "full"
}).format(new Date());

В Luxon:

DateTime.now()
  .setLocale("ja-JP-u-ca-japanese")
  .toLocaleString(DateTime.DATE_FULL);

Luxon предоставляет:

  • удобную работу с immutable-объектами;
  • timezone API;
  • арифметику дат;
  • цепочки преобразований;
  • единый интерфейс.

Практический пример мультиязычного интерфейса

const users = [
  {
    locale: "en",
    calendar: "gregory"
  },
  {
    locale: "ar",
    calendar: "islamic"
  },
  {
    locale: "ja",
    calendar: "japanese"
  }
];

const now = DateTime.now();

for (const user of users) {
  const formatted = now.reconfigure({
    locale: user.locale,
    outputCalendar: user.calendar
  });

  console.log(
    formatted.toLocaleString(
      DateTime.DATE_FULL
    )
  );
}

Использование setLocale вместо reconfigure

const date = DateTime.now()
  .setLocale("fa")
  .reconfigure({
    outputCalendar: "persian"
  });

Разделение локали и календаря делает код более читаемым.


Иммутабельность объектов

Все операции создают новый экземпляр.

const original = DateTime.now();

const japanese = original.reconfigure({
  outputCalendar: "japanese"
});

console.log(original === japanese);

Результат:

false

Исходный объект не изменяется.


Комбинирование параметров локализации

const date = DateTime.now().reconfigure({
  locale: "ar",
  outputCalendar: "islamic",
  numberingSystem: "arab",
  weekSettings: {
    firstDay: 6
  }
});

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


Когда использовать альтернативные календари

Типичные сценарии:

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

Основные рекомендации

Использовать toLocaleString()

Для корректной локализации предпочтительнее:

toLocaleString()

а не:

toFormat()

Проверять поддержку календаря

Intl.supportedValuesOf("calendar")

Не изменять бизнес-логику

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


Учитывать различия платформ

Одинаковый код может давать разные результаты:

  • в браузере;
  • в Node.js;
  • на мобильных устройствах;
  • в серверных средах.