Конвертация между календарями

В JavaScript объект Date всегда хранит момент времени как количество миллисекунд с эпохи Unix (UTC). Календарь в Intl не изменяет внутреннее представление даты, а влияет только на способ её интерпретации и отображения.

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

Ключевая особенность:

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

Календарь как часть локали Unicode Extension

Календарь может быть задан через Unicode extension в строке локали:

const locale = "en-US-u-ca-islamic";

Фрагмент u-ca-islamic указывает календарную систему:

  • ca — calendar
  • islamic — исламский календарь

Пример использования:

const date = new Date("2026-01-01T00:00:00Z");

console.log(new Intl.DateTimeFormat("en-US-u-ca-gregory").format(date));
console.log(new Intl.DateTimeFormat("en-US-u-ca-islamic").format(date));

Обе строки используют один и тот же Date, но вывод будет различаться из-за календарной системы.


Intl.DateTimeFormat и параметр calendar

Второй способ задания календаря — через опции форматтера:

const formatter = new Intl.DateTimeFormat("en-US", {
  calendar: "islamic"
});

console.log(formatter.format(new Date()));

Этот вариант эквивалентен использованию Unicode extension, но даёт более явный контроль в коде.


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

Часто используемые значения calendar:

  • gregory — григорианский календарь (по умолчанию)
  • islamic — исламский (обобщённый)
  • islamic-umalqura — исламский календарь Умм аль-Кура
  • buddhist — буддийский календарь
  • japanese — японская система эр

Пример:

const calendars = ["gregory", "buddhist", "japanese"];

const date = new Date("2026-05-27T00:00:00Z");

for (const cal of calendars) {
  const f = new Intl.DateTimeFormat("en-US", {
    calendar: cal,
    year: "numeric",
    month: "long",
    day: "numeric"
  });

  console.log(cal, "->", f.format(date));
}

Важный принцип: преобразование не является пересчётом даты

Календарная система в Intl не изменяет момент времени. Это не арифметическая конвертация между календарями, а отображение одного и того же timestamp в разных системах.

Например:

const date = new Date("2026-05-27T12:00:00Z");

Этот момент:

  • не становится «другой датой» в исламском или японском календаре
  • просто отображается с другими правилами вычисления года/месяца/дня

Локаль и влияние календаря на форматирование

Календарь тесно связан с локалью:

const f1 = new Intl.DateTimeFormat("ar-SA", {
  calendar: "islamic"
});

const f2 = new Intl.DateTimeFormat("ar-SA", {
  calendar: "gregory"
});

console.log(f1.format(new Date()));
console.log(f2.format(new Date()));

Даже при одинаковой локали результат может радикально отличаться, поскольку:

  • меняется структура месяцев
  • меняется номер года
  • меняются названия периодов

Чтение и анализ локали через Intl.Locale

Intl.Locale позволяет извлечь информацию о календаре:

const loc = new Intl.Locale("en-US-u-ca-buddhist");

console.log(loc.calendar); // "buddhist"

Это полезно для:

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

Переключение календарей без изменения даты

Типичный сценарий — динамическое переключение календарной системы:

function format(date, calendar) {
  return new Intl.DateTimeFormat("en-US", {
    calendar,
    year: "numeric",
    month: "long",
    day: "numeric"
  }).format(date);
}

const date = new Date("2026-05-27T00:00:00Z");

console.log(format(date, "gregory"));
console.log(format(date, "islamic-umalqura"));
console.log(format(date, "buddhist"));

Здесь одна дата отображается в трёх календарных системах без каких-либо преобразований самого объекта Date.


Ограничения модели календарей в Intl

Механизм календарей в Intl имеет ряд принципиальных ограничений:

Отсутствие обратного преобразования

Невозможно получить Date из строки, сформированной в другом календаре:

const formatted = new Intl.DateTimeFormat("ar-SA-u-ca-islamic").format(new Date());
// обратно в Date стандартными средствами Intl это не конвертируется

Отсутствие математической конверсии календарей

Intl не предоставляет API для:

  • перевода исламской даты в григорианскую как структуры (год/месяц/день)
  • выполнения календарной арифметики

Он работает только на уровне форматирования.


Практическая модель восприятия календарей

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

  1. Date хранит абсолютный момент времени

  2. Intl.DateTimeFormat получает этот момент

  3. календарь определяет правила разбиения времени на:

    • год
    • месяц
    • день
  4. результат формируется как строка


Unicode extension и сложные комбинации календарей

Локаль может содержать сразу несколько расширений:

const locale = "ar-SA-u-ca-islamic-nu-latn";

Где:

  • ca-islamic — календарь
  • nu-latn — система чисел (латинские цифры)

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

const f = new Intl.DateTimeFormat(locale, {
  year: "numeric",
  month: "long",
  day: "numeric"
});

console.log(f.format(new Date()));

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

Если календарь не поддерживается окружением:

  • происходит fallback к gregory
  • либо к ближайшей доступной системе

Пример:

new Intl.DateTimeFormat("en-US", {
  calendar: "unknown-calendar"
}).format(new Date());

Результат зависит от реализации движка, но обычно система игнорирует неизвестное значение.


Сравнение отображения одной даты в разных календарях

const date = new Date("2026-05-27T00:00:00Z");

const options = { year: "numeric", month: "long", day: "numeric" };

const greg = new Intl.DateTimeFormat("en-US-u-ca-gregory", options);
const islam = new Intl.DateTimeFormat("en-US-u-ca-islamic", options);
const japan = new Intl.DateTimeFormat("en-US-u-ca-japanese", options);

console.log(greg.format(date));
console.log(islam.format(date));
console.log(japan.format(date));

Каждый форматтер использует:

  • один и тот же timestamp
  • разные правила календарного разбиения

Роль календарей в интернационализации интерфейсов

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

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

В системах с несколькими календарями важно:

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