How do I display year and era in non-Gregorian calendars?

Use the calendar and era options in Intl.DateTimeFormat to show years and eras from Islamic, Hebrew, Chinese, Persian, and other calendar systems

Introduction

The Gregorian calendar counts years from a single starting point, making year 2024 a straightforward number. Other calendar systems count years differently. The Islamic calendar counts from the year 622 CE. The Hebrew calendar counts from a traditional creation date thousands of years ago. The Chinese calendar uses a 60-year cycle of named years instead of sequential numbers.

These different counting systems mean that the same moment in time has different year representations across calendars. October 15, 2024 in the Gregorian calendar is year 1446 in the Islamic calendar, year 5785 in the Hebrew calendar, and year 2024 (甲辰, jiǎ-chén) in the Chinese calendar.

JavaScript's Intl.DateTimeFormat provides options to display years and eras from any calendar system. The calendar option selects which calendar to use. The year and era options control how the year and era display. For calendars that use named years instead of numbers, the formatToParts() method provides access to both the year name and the corresponding Gregorian year.

How years differ across calendar systems

Calendar systems differ in three fundamental ways: where they start counting, how they number years, and whether they use eras.

The Gregorian calendar starts counting from year 1 CE and increments sequentially. The Islamic calendar starts from year 1 AH (After Hijra) in 622 CE. The Hebrew calendar starts from year 1 in 3761 BCE. Each calendar has its own epoch, the point where year counting begins.

Some calendars use sequential year numbers that increase forever. The Gregorian, Islamic, Hebrew, and Persian calendars work this way. Other calendars use cycles where year names repeat. The Chinese calendar uses a 60-year cycle of named years. After 60 years, the cycle repeats.

Eras divide time into named periods. The Gregorian calendar uses BC and AD. The Japanese calendar uses imperial era names. The Islamic and Hebrew calendars typically use a single era that began at their epoch. The Chinese calendar does not use eras in the same way, relying instead on named years within cycles.

Display years in Islamic calendar

The Islamic calendar counts years from the Hijra, Muhammad's migration from Mecca to Medina in 622 CE. The Islamic year 1 corresponds to the Gregorian year 622. The Islamic calendar uses lunar months, making its years shorter than Gregorian years. This means the Islamic year advances faster, currently reaching year 1446 when the Gregorian year is 2024.

You specify the Islamic calendar using the calendar option with the value islamic or by adding the Unicode extension -u-ca-islamic to the locale identifier.

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"

The year displays as 1446, which is the Islamic year corresponding to October 15, 2024. The era "AH" (After Hijra) appears automatically when displaying Islamic dates in English.

Different locales format Islamic dates according to their conventions.

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));
// "١٢ ربيع الآخر ١٤٤٦ هـ"

The Arabic locale uses Arabic-Indic numerals and displays the month name in Arabic. The era indicator changes to "هـ" (the Arabic abbreviation for Hijri).

Control era display in Islamic calendar

The era option controls whether and how the era indicator displays. The option accepts three values: long for the full era name, short for an abbreviation, and narrow for the most compact form.

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"

The long value produces "Anno Hegirae" (Latin for "in the year of the Hijra"). The short value produces "AH". The narrow value produces just "A".

Islamic calendar variants

The Islamic calendar has several variants that use different calculation methods. JavaScript supports five variants: islamic, islamic-civil, islamic-tbla, islamic-umalqura, and islamic-rgsa.

The islamic-umalqura variant uses the official calendar of Saudi Arabia, which is based on astronomical observations. The islamic-civil variant uses a fixed arithmetic calculation with alternating 29 and 30-day months.

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"

The variants can produce different day numbers for the same Gregorian date because they use different calculation methods to determine month boundaries.

Display years in Hebrew calendar

The Hebrew calendar counts years from a traditional creation date in 3761 BCE. This makes Hebrew years much larger than Gregorian years. The Hebrew year 5785 corresponds to the Gregorian year 2024.

You specify the Hebrew calendar using the calendar option with the value hebrew or by adding the Unicode extension -u-ca-hebrew to the locale identifier.

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"

The year displays as 5785, which is the Hebrew year corresponding to October 15, 2024. The Hebrew calendar is lunisolar, meaning its months follow the moon but its years stay synchronized with the solar year through periodic leap months.

Hebrew dates in Hebrew locale use Hebrew numerals and month names.

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));
// "י״ג בתשרי ה׳תשפ״ה"

The Hebrew locale displays the date entirely in Hebrew, including Hebrew letters used as numerals.

Display years in Chinese calendar

The Chinese calendar uses a 60-year cycle of named years instead of sequential year numbers. Each year in the cycle has a name composed of two characters: a heavenly stem and an earthly branch. The year 2024 is 甲辰 (jiǎ-chén), which means "wood dragon" in traditional Chinese astrology.

Because the Chinese calendar uses named years, displaying it requires different handling than calendars with sequential year numbers.

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)"

The formatted output includes both the Gregorian year 2024 and the year name "jiǎ-chén" in parentheses. This dual representation helps users understand both the cyclical year name and the corresponding Gregorian year.

Chinese dates in Chinese locale display using Chinese characters.

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甲辰年九月十三"

The Chinese locale displays the year name using Chinese characters. The format integrates the year name naturally into the date string.

Calendars that use named years provide two pieces of information: the year name within the cycle and the corresponding Gregorian year. The formatToParts() method separates these into distinct parts.

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);

The parts array includes two relevant entries:

[
  { type: 'relatedYear', value: '2024' },
  { type: 'yearName', value: '甲辰' },
  // ... other parts
]

The relatedYear part contains the four-digit Gregorian year. The yearName part contains the cyclical year name. This separation allows you to use either or both values in custom formatting.

You can extract these parts to create custom date displays.

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"

This technique works with any calendar that uses named years or cycles.

Display years in Persian calendar

The Persian calendar, also known as the Solar Hijri calendar, counts years from the Hijra in 622 CE, the same epoch as the Islamic calendar. However, the Persian calendar uses solar months instead of lunar months, making it more similar to the Gregorian calendar in structure.

You specify the Persian calendar using the calendar option with the value persian or by adding the Unicode extension -u-ca-persian to the locale identifier.

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"

The year displays as 1403, which is the Persian year corresponding to October 15, 2024. The era "AP" (Anno Persico) appears in the English format.

Persian dates in Persian locale use Persian numerals and month names.

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));
// "۲۴ مهر ۱۴۰۳ ه‍.ش."

The Persian locale displays the date using Persian (Farsi) characters and numerals. The era indicator "ه‍.ش." is the Persian abbreviation for the Solar Hijri era.

Combine calendar and era options

You can combine the calendar and era options to control exactly how years and eras display across different calendar systems. This combination gives you precise control over date formatting.

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"

The Gregorian and Islamic dates display their era indicators because the era option is set. The Hebrew date does not show an era indicator in this format, as Hebrew calendar formatting typically omits it.

You can also mix locales and calendars to display dates in one language using another culture's calendar.

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));
// "١٢ ربيع الآخر ١٤٤٦ هـ"

Both formatters use the Islamic calendar, but the English locale produces English month names and Latin numerals while the Arabic locale produces Arabic month names and Arabic-Indic numerals.

Display years across multiple calendars

Applications that serve international audiences often need to display the same date in multiple calendar systems. You can create multiple formatters to show parallel representations.

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)}`);
});

This produces:

Gregorian: October 15, 2024
Islamic: Rabi' II 12, 1446 AH
Hebrew: Tishrei 13, 5785
Persian: Mehr 24, 1403 AP

Each calendar represents the same moment in time using its own year counting system and era indicators.

Common use cases

International applications need to display dates in the calendar systems their users expect. An Islamic banking application displays transaction dates using the Islamic calendar.

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: ١٢ ربيع الآخر ١٤٤٦ هـ"

Religious calendars determine the dates of holidays and observances. A Jewish calendar application displays Hebrew dates for holidays.

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: א׳ בתשרי ה׳תשפ״ה"

Historical applications display dates in the calendar systems used at the time. An application about ancient Persia displays dates using the Persian calendar.

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"

Summary

Non-Gregorian calendars count years from different starting points and use different numbering systems. The Islamic calendar counts from year 622 CE and currently displays years around 1446. The Hebrew calendar counts from 3761 BCE and displays years around 5785. The Chinese calendar uses a 60-year cycle of named years instead of sequential numbers.

JavaScript's Intl.DateTimeFormat supports these calendar systems through the calendar option. Values include islamic, hebrew, chinese, persian, and others. The year option controls whether the year displays, and the era option controls whether and how the era indicator displays.

Calendars that use named years provide two pieces of information through formatToParts(). The yearName part contains the cyclical year name. The relatedYear part contains the corresponding Gregorian year. This allows applications to display either or both values.

Different locales format the same calendar in different ways. The Islamic calendar displays in English with Latin numerals and in Arabic with Arabic-Indic numerals. The formatting automatically adapts to locale conventions while maintaining the calendar's year numbering system.