Как отобразить год и эру в не-григорианских календарях?
Используйте параметры calendar и era в Intl.DateTimeFormat, чтобы показывать годы и эры исламского, еврейского, китайского, персидского и других календарей
Введение
Григорианский календарь ведёт отсчёт лет от одной точки отсчёта, поэтому 2024 год — это просто число. В других календарных системах годы считаются иначе. В исламском календаре отсчёт ведётся с 622 года н.э. В еврейском календаре — с традиционной даты сотворения мира, насчитывающей тысячи лет. Китайский календарь использует 60-летний цикл именных лет вместо последовательных чисел.
Из-за этих различий в системах отсчёта один и тот же момент времени будет иметь разные обозначения года в разных календарях. 15 октября 2024 года по григорианскому календарю — это 1446 год по исламскому календарю, 5785 год по еврейскому календарю и 2024 год (甲辰, jiǎ-chén) по китайскому календарю.
В JavaScript Intl.DateTimeFormat предоставляет параметры для отображения годов и эр из любой календарной системы. Параметр calendar определяет, какой календарь использовать. Параметры year и era управляют тем, как отображаются год и эра. Для календарей, где используются имена лет вместо чисел, метод formatToParts() позволяет получить как название года, так и соответствующий григорианский год.
Как годы различаются в разных календарных системах
Календарные системы различаются по трём основным признакам: с какой точки начинается отсчёт, как нумеруются годы и используются ли эры.
Григорианский календарь начинает отсчёт с 1 года н.э. и увеличивает его последовательно. Исламский календарь начинается с 1 года AH (после хиджры) в 622 году н.э. Еврейский календарь начинается с 1 года в 3761 году до н.э. У каждого календаря есть своя эпоха — точка, с которой начинается отсчёт лет.
В некоторых календарях используются последовательные номера лет, которые увеличиваются бесконечно. Так работают григорианский, исламский, еврейский и персидский календари. В других календарях используются циклы, где названия лет повторяются. Например, в китайском календаре есть 60-летний цикл с уникальными названиями лет. После 60 лет цикл начинается заново.
Эры делят время на именованные периоды. В григорианском календаре используются обозначения до н.э. и н.э. В японском календаре применяются имена императорских эр. В исламском и еврейском календарях обычно используется одна эра, начавшаяся с их эпохи. В китайском календаре эры не используются в таком виде — вместо этого применяются названия лет внутри циклов.
Отображение лет в исламском календаре
В исламском календаре годы отсчитываются от Хиджры — переселения Мухаммеда из Мекки в Медину в 622 году н.э. Исламский 1 год соответствует 622 году по григорианскому календарю. В исламском календаре используются лунные месяцы, поэтому годы короче, чем в григорианском календаре. Из-за этого исламский год идёт быстрее, и сейчас (в 2024 году) наступил 1446 год по исламскому летоисчислению.
Вы можете указать исламский календарь с помощью опции calendar со значением islamic или добавив расширение Unicode -u-ca-islamic к идентификатору локали.
const date = new Date('2024-10-15');
const formatter = new Intl.DateTimeFormat('en-US', {
calendar: 'islamic',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(formatter.format(date));
// "Rabi' II 12, 1446 AH"
Год отображается как 1446 — это исламский год, соответствующий 15 октября 2024 года. Эра «AH» (после Хиджры) появляется автоматически при отображении исламских дат на английском языке.
В разных локалях исламские даты форматируются по-разному.
const date = new Date('2024-10-15');
const en = new Intl.DateTimeFormat('en-US', {
calendar: 'islamic',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(en.format(date));
// "Rabi' II 12, 1446 AH"
const ar = new Intl.DateTimeFormat('ar-SA', {
calendar: 'islamic',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(ar.format(date));
// "١٢ ربيع الآخر ١٤٤٦ هـ"
В арабской локали используются арабско-индийские цифры и название месяца на арабском языке. Индикатор эры меняется на «هـ» (арабская аббревиатура Хиджры).
Управление отображением эры в исламском календаре
Параметр era определяет, будет ли и как отображаться индикатор эры. Доступны три значения: long — для полного названия эры, short — для сокращённого варианта, и narrow — для самого компактного формата.
const date = new Date('2024-10-15');
const long = new Intl.DateTimeFormat('en-US', {
calendar: 'islamic',
year: 'numeric',
era: 'long'
});
console.log(long.format(date));
// "1446 Anno Hegirae"
const short = new Intl.DateTimeFormat('en-US', {
calendar: 'islamic',
year: 'numeric',
era: 'short'
});
console.log(short.format(date));
// "1446 AH"
const narrow = new Intl.DateTimeFormat('en-US', {
calendar: 'islamic',
year: 'numeric',
era: 'narrow'
});
console.log(narrow.format(date));
// "1446 A"
Значение long выводит «Anno Hegirae» (на латыни — «в год Хиджры»). Значение short выводит «AH». Значение narrow выводит только «A».
Варианты исламского календаря
В исламском календаре есть несколько вариантов, использующих разные методы расчёта. JavaScript поддерживает пять вариантов: islamic, islamic-civil, islamic-tbla, islamic-umalqura и islamic-rgsa.
Вариант islamic-umalqura использует официальный календарь Саудовской Аравии, основанный на астрономических наблюдениях. Вариант islamic-civil использует фиксированный арифметический расчёт с чередованием месяцев по 29 и 30 дней.
const date = new Date('2024-10-15');
const umalqura = new Intl.DateTimeFormat('en-US', {
calendar: 'islamic-umalqura',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(umalqura.format(date));
// "Rabi' II 12, 1446 AH"
const civil = new Intl.DateTimeFormat('en-US', {
calendar: 'islamic-civil',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(civil.format(date));
// "Rabi' II 11, 1446 AH"
Варианты могут давать разные номера дней для одной и той же григорианской даты, потому что используют разные методы расчёта для определения границ месяцев.
Отображение лет в еврейском календаре
Еврейский календарь отсчитывает годы от традиционной даты сотворения мира в 3761 году до н. э. Поэтому годы в еврейском календаре значительно больше, чем в григорианском. Например, 5785 год по еврейскому календарю соответствует 2024 году по григорианскому.
Вы можете указать еврейский календарь с помощью параметра calendar со значением hebrew или добавив расширение Unicode -u-ca-hebrew к идентификатору локали.
const date = new Date('2024-10-15');
const formatter = new Intl.DateTimeFormat('en-US', {
calendar: 'hebrew',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(formatter.format(date));
// "Tishrei 13, 5785"
Год отображается как 5785 — это еврейский год, соответствующий 15 октября 2024 года. Еврейский календарь лунно-солнечный: месяцы следуют за лунным циклом, а годы синхронизируются с солнечным годом за счёт периодических високосных месяцев.
В еврейской локали даты отображаются с использованием еврейских цифр и названий месяцев.
const date = new Date('2024-10-15');
const he = new Intl.DateTimeFormat('he-IL', {
calendar: 'hebrew',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(he.format(date));
// "י״ג בתשרי ה׳תשפ״ה"
В еврейской локали дата полностью отображается на иврите, включая буквы, используемые в качестве цифр.
Отображение лет в китайском календаре
В китайском календаре используется 60-летний цикл именных лет вместо последовательных номеров. Каждое годовое имя состоит из двух иероглифов: небесного ствола и земной ветви. 2024 год — это 甲辰 (jiǎ-chén), что в традиционной китайской астрологии означает «древесный дракон».
Поскольку в китайском календаре используются имена лет, для его отображения требуется иной подход, чем для календарей с последовательной нумерацией лет.
const date = new Date('2024-10-15');
const formatter = new Intl.DateTimeFormat('en-US', {
calendar: 'chinese',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(formatter.format(date));
// "Ninth Month 13, 2024(jiǎ-chén)"
Отформатированный вывод включает как григорианский год 2024, так и имя года «jiǎ-chén» в скобках. Такое двойное представление помогает пользователям понять и циклическое имя года, и соответствующий григорианский год.
Китайские даты в китайской локали отображаются с использованием китайских иероглифов.
const date = new Date('2024-10-15');
const zh = new Intl.DateTimeFormat('zh-CN', {
calendar: 'chinese',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(zh.format(date));
// "2024甲辰年九月十三"
В китайской локали имя года отображается с помощью китайских иероглифов. Формат естественно интегрирует имя года в строку даты.
Извлечение имени года и связанного года
Календари с именными годами предоставляют две информации: имя года в цикле и соответствующий григорианский год. Метод formatToParts() разделяет их на отдельные части.
const date = new Date('2024-10-15');
const formatter = new Intl.DateTimeFormat('zh-CN', {
calendar: 'chinese',
year: 'numeric',
month: 'long',
day: 'numeric'
});
const parts = formatter.formatToParts(date);
console.log(parts);
Массив parts содержит два важных элемента:
[
{ type: 'relatedYear', value: '2024' },
{ type: 'yearName', value: '甲辰' },
// ... other parts
]
Часть relatedYear содержит четырехзначный григорианский год. Часть yearName содержит циклическое имя года. Такое разделение позволяет использовать одно или оба значения для кастомного форматирования.
Вы можете выделить эти части, чтобы создать собственные варианты отображения даты.
const date = new Date('2024-10-15');
const formatter = new Intl.DateTimeFormat('zh-CN', {
calendar: 'chinese',
year: 'numeric',
month: 'long',
day: 'numeric'
});
const parts = formatter.formatToParts(date);
const yearName = parts.find(p => p.type === 'yearName')?.value;
const relatedYear = parts.find(p => p.type === 'relatedYear')?.value;
console.log(`Year name: ${yearName}`);
// "Year name: 甲辰"
console.log(`Gregorian year: ${relatedYear}`);
// "Gregorian year: 2024"
Этот способ работает с любым календарём, в котором используются имена лет или циклы.
Отображение лет в персидском календаре
Персидский календарь, также известный как солнечный хиджра-календарь, отсчитывает годы от хиджры в 622 году н.э., как и исламский календарь. Однако в персидском календаре используются солнечные месяцы вместо лунных, поэтому по структуре он ближе к григорианскому календарю.
Вы указываете персидский календарь с помощью опции calendar со значением persian или добавляя расширение Unicode -u-ca-persian к идентификатору локали.
const date = new Date('2024-10-15');
const formatter = new Intl.DateTimeFormat('en-US', {
calendar: 'persian',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(formatter.format(date));
// "Mehr 24, 1403 AP"
Год отображается как 1403 — это персидский год, соответствующий 15 октября 2024 года. Эра «AP» (Anno Persico) появляется в английском формате.
Персидские даты в персидской локали используют персидские цифры и названия месяцев.
const date = new Date('2024-10-15');
const fa = new Intl.DateTimeFormat('fa-IR', {
calendar: 'persian',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(fa.format(date));
// "۲۴ مهر ۱۴۰۳ ه.ش."
В персидской локали дата отображается с использованием персидских (фарси) символов и цифр. Индикатор эры «ه.ش.» — это персидская аббревиатура солнечной хиджры.
Комбинирование опций календаря и эры
Вы можете комбинировать опции calendar и era, чтобы точно управлять тем, как отображаются годы и эры в разных календарных системах. Такая комбинация даёт полный контроль над форматированием дат.
const date = new Date('2024-10-15');
const gregorian = new Intl.DateTimeFormat('en-US', {
calendar: 'gregory',
year: 'numeric',
month: 'long',
era: 'short'
});
console.log(gregorian.format(date));
// "October 2024 AD"
const islamic = new Intl.DateTimeFormat('en-US', {
calendar: 'islamic',
year: 'numeric',
month: 'long',
era: 'short'
});
console.log(islamic.format(date));
// "Rabi' II 1446 AH"
const hebrew = new Intl.DateTimeFormat('en-US', {
calendar: 'hebrew',
year: 'numeric',
month: 'long',
era: 'short'
});
console.log(hebrew.format(date));
// "Tishrei 5785"
Григорианские и исламские даты показывают свои индикаторы эры, потому что установлена опция era. В еврейской дате индикатор эры не отображается, так как в форматировании еврейского календаря он обычно опускается.
Вы также можете комбинировать локали и календари, чтобы отображать даты на одном языке, используя календарь другой культуры.
const date = new Date('2024-10-15');
const englishIslamic = new Intl.DateTimeFormat('en-US', {
calendar: 'islamic',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(englishIslamic.format(date));
// "Rabi' II 12, 1446 AH"
const arabicIslamic = new Intl.DateTimeFormat('ar-SA', {
calendar: 'islamic',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(arabicIslamic.format(date));
// "١٢ ربيع الآخر ١٤٤٦ هـ"
Оба форматтера используют исламский календарь, но локаль английского языка выводит английские названия месяцев и латинские цифры, а арабская локаль — арабские названия месяцев и арабо-индийские цифры.
Отображение лет в разных календарях
Приложения для международной аудитории часто должны показывать одну и ту же дату в нескольких календарных системах. Вы можете создать несколько форматтеров для параллельного отображения.
const date = new Date('2024-10-15');
const calendars = [
{ name: 'Gregorian', calendar: 'gregory' },
{ name: 'Islamic', calendar: 'islamic' },
{ name: 'Hebrew', calendar: 'hebrew' },
{ name: 'Persian', calendar: 'persian' }
];
calendars.forEach(cal => {
const formatter = new Intl.DateTimeFormat('en-US', {
calendar: cal.calendar,
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(`${cal.name}: ${formatter.format(date)}`);
});
В результате получится:
Gregorian: October 15, 2024
Islamic: Rabi' II 12, 1446 AH
Hebrew: Tishrei 13, 5785
Persian: Mehr 24, 1403 AP
Каждый календарь отображает один и тот же момент времени, используя свою систему летоисчисления и обозначения эпох.
Типовые сценарии использования
Международные приложения должны показывать даты в тех календарных системах, к которым привыкли их пользователи. Например, исламское банковское приложение отображает даты транзакций по исламскому календарю.
const transactionDate = new Date('2024-10-15');
const formatter = new Intl.DateTimeFormat('ar-SA', {
calendar: 'islamic-umalqura',
year: 'numeric',
month: 'long',
day: 'numeric',
era: 'short'
});
console.log(`Transaction date: ${formatter.format(transactionDate)}`);
// "Transaction date: ١٢ ربيع الآخر ١٤٤٦ هـ"
Религиозные календари определяют даты праздников и обрядов. Например, еврейское календарное приложение показывает еврейские даты праздников.
const roshHashanah2024 = new Date('2024-10-03');
const formatter = new Intl.DateTimeFormat('he-IL', {
calendar: 'hebrew',
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(`Rosh Hashanah: ${formatter.format(roshHashanah2024)}`);
// "Rosh Hashanah: א׳ בתשרי ה׳תשפ״ה"
Исторические приложения отображают даты в календарных системах, использовавшихся в то время. Например, приложение о Древней Персии показывает даты по персидскому календарю.
const historicalDate = new Date('2024-03-20');
const formatter = new Intl.DateTimeFormat('en-US', {
calendar: 'persian',
year: 'numeric',
month: 'long',
day: 'numeric',
era: 'long'
});
console.log(`Persian New Year: ${formatter.format(historicalDate)}`);
// "Persian New Year: Farvardin 1, 1403 Anno Persico"
Итоги
Некоторые календари, отличные от григорианского, ведут летоисчисление с разных точек отсчёта и используют разные системы нумерации. Исламский календарь ведёт отсчёт с 622 года н.э. и сейчас показывает примерно 1446 год. Еврейский календарь ведёт отсчёт с 3761 года до н.э. и сейчас показывает примерно 5785 год. Китайский календарь использует 60-летний цикл именных лет вместо последовательной нумерации.
JavaScript Intl.DateTimeFormat поддерживает эти календарные системы через опцию calendar. Среди значений — islamic, hebrew, chinese, persian и другие. Опция year управляет отображением года, а era — отображением и форматом индикатора эпохи.
Календари, использующие имена лет, предоставляют две информации через formatToParts(). Часть yearName содержит циклическое имя года. Часть relatedYear содержит соответствующий год по григорианскому календарю. Это позволяет приложениям отображать одно или оба значения.
В разных локалях один и тот же календарь форматируется по-разному. Например, исламский календарь отображается на английском с латинскими цифрами, а на арабском — с арабо-индийскими цифрами. Форматирование автоматически подстраивается под конвенции локали, сохраняя систему нумерации лет календаря.