Get list of available calendar systems

Discover which calendar systems your JavaScript environment supports

Introduction

When building applications for a global audience, users often need to view dates in their preferred calendar system. While you might be familiar with the Gregorian calendar used in most Western countries, many cultures use entirely different calendar systems like the Islamic Hijri calendar, Hebrew calendar, or Buddhist calendar.

To let users select their preferred calendar, you need to know which calendar systems the JavaScript environment supports. Rather than maintaining a hardcoded list that becomes outdated or includes unsupported values, JavaScript provides a method to discover available calendar systems at runtime.

The Intl.supportedValuesOf() method with the "calendar" parameter returns an array of all calendar system identifiers supported by the current environment. This ensures your application only offers calendar options that work correctly.

What calendar systems are

Calendar systems are different methods of organizing and counting time. While all calendars track days, months, and years, they use different rules for calculating when a year begins, how long months last, and how to account for astronomical cycles.

The Gregorian calendar, introduced in 1582, is the most widely used civil calendar. It uses a solar year of approximately 365.25 days, divided into 12 months, with leap years added every four years (with exceptions for century years).

Other calendar systems follow different rules. The Islamic calendar is purely lunar, with months following the moon's phases. This means the Islamic year is about 11 days shorter than a solar year, causing Islamic dates to shift through the seasons over time. The Hebrew and Chinese calendars are lunisolar, combining lunar months with adjustments to keep the calendar synchronized with the solar year.

When you format dates in JavaScript, the calendar system determines which year, month, and day numbers appear. The same moment in time has different date representations in different calendar systems.

Using Intl.supportedValuesOf to get calendar systems

The Intl.supportedValuesOf() method accepts a string parameter specifying which type of values to return. To get calendar systems, pass "calendar":

const calendars = Intl.supportedValuesOf("calendar");
console.log(calendars);
// Output: ["buddhist", "chinese", "coptic", "dangi", "ethioaa",
//          "ethiopic", "gregory", "hebrew", "indian", "islamic",
//          "islamic-civil", "islamic-rgsa", "islamic-tbla",
//          "islamic-umalqura", "iso8601", "japanese", "persian", "roc"]

The method returns an array of strings representing calendar identifiers. These identifiers follow the Unicode CLDR (Common Locale Data Repository) standard, which provides a consistent way to reference calendar systems across different platforms and programming languages.

The returned array has these characteristics:

  • Values are sorted in ascending alphabetical order
  • Duplicate values are removed
  • Each identifier uses lowercase letters and hyphens
  • The list includes all calendar systems supported by the JavaScript implementation

Different browsers and JavaScript environments support different sets of calendars, though all modern browsers support a core set of common calendars.

Understanding calendar identifiers

Each calendar identifier represents a specific calendar system used by one or more cultures. Here are the most common identifiers:

The "gregory" identifier represents the Gregorian calendar, the standard civil calendar used in most countries. This is the calendar you use in everyday life if you live in the United States, Europe, or most other parts of the world.

The "buddhist" identifier represents the Thai Buddhist calendar, which uses the same month and day structure as the Gregorian calendar but counts years from the birth of Buddha (543 BCE in the Gregorian calendar). Year 2025 in the Gregorian calendar is year 2568 in the Buddhist calendar.

The "chinese" identifier represents the traditional Chinese calendar, a lunisolar calendar where months follow the moon's phases and years align with Jupiter's orbital period. The Chinese calendar is used to determine traditional holidays like Chinese New Year.

The "islamic" identifier represents the Islamic Hijri calendar, a purely lunar calendar with 12 months of 29 or 30 days. Years are counted from the Hijra, when Muhammad migrated from Mecca to Medina in 622 CE.

The "hebrew" identifier represents the Hebrew calendar, a lunisolar calendar used for Jewish religious observances. It counts years from a traditional creation date (3761 BCE in the Gregorian calendar).

The "japanese" identifier represents the Japanese calendar, which uses the same month and day structure as the Gregorian calendar but divides time into eras based on the reigning emperor. The current era is Reiwa, which began in 2019.

The "persian" identifier represents the Solar Hijri calendar used in Iran and Afghanistan. It is a solar calendar with years counted from the Hijra, making it different from the lunar Islamic calendar.

Additional identifiers include "coptic" (Coptic Orthodox calendar), "dangi" (traditional Korean calendar), "ethiopic" (Ethiopian calendar), "indian" (Indian national calendar), and "roc" (Republic of China calendar used in Taiwan).

Some identifiers have variants like "islamic-civil", "islamic-rgsa", "islamic-tbla", and "islamic-umalqura", which represent different calculation methods for the Islamic calendar.

The "iso8601" identifier represents the ISO 8601 calendar, which is essentially the Gregorian calendar but always uses the proleptic Gregorian calendar (extending the Gregorian calendar backwards before its introduction in 1582).

Seeing calendar systems in action

To understand how calendar systems affect date formatting, format the same date using different calendars:

const date = new Date("2025-10-15");

const gregorian = new Intl.DateTimeFormat("en-US", {
  calendar: "gregory",
  year: "numeric",
  month: "long",
  day: "numeric"
});

const islamic = new Intl.DateTimeFormat("en-US", {
  calendar: "islamic",
  year: "numeric",
  month: "long",
  day: "numeric"
});

const hebrew = new Intl.DateTimeFormat("en-US", {
  calendar: "hebrew",
  year: "numeric",
  month: "long",
  day: "numeric"
});

const buddhist = new Intl.DateTimeFormat("en-US", {
  calendar: "buddhist",
  year: "numeric",
  month: "long",
  day: "numeric"
});

console.log(gregorian.format(date));
// Output: "October 15, 2025"

console.log(islamic.format(date));
// Output: "Rabi' II 16, 1447 AH"

console.log(hebrew.format(date));
// Output: "Tishrei 23, 5786"

console.log(buddhist.format(date));
// Output: "October 15, 2568 BE"

The same JavaScript Date object represents the same moment in time, but each calendar system expresses that moment with different year, month, and day values. The Gregorian date October 15, 2025 corresponds to Rabi' II 16, 1447 in the Islamic calendar, Tishrei 23, 5786 in the Hebrew calendar, and October 15, 2568 in the Buddhist calendar.

This demonstrates why you need to specify which calendar system to use when formatting dates for users who follow different calendars.

Building a calendar selector

When creating user interfaces that let users choose their preferred calendar, query the available calendars and build a selector dynamically:

function buildCalendarSelector() {
  const calendars = Intl.supportedValuesOf("calendar");
  const select = document.createElement("select");
  select.id = "calendar-selector";

  calendars.forEach(calendar => {
    const option = document.createElement("option");
    option.value = calendar;
    option.textContent = calendar;
    select.appendChild(option);
  });

  return select;
}

const selector = buildCalendarSelector();
document.body.appendChild(selector);

This creates a dropdown containing every supported calendar. However, the technical identifiers like "gregory" and "islamic" are not user-friendly. Users need to see descriptive names in their own language.

Displaying human-readable calendar names

The Intl.DisplayNames API converts calendar identifiers into human-readable names. Use it to create a better calendar selector:

function buildCalendarSelector(locale = "en-US") {
  const calendars = Intl.supportedValuesOf("calendar");
  const displayNames = new Intl.DisplayNames([locale], { type: "calendar" });

  const select = document.createElement("select");
  select.id = "calendar-selector";

  calendars.forEach(calendar => {
    const option = document.createElement("option");
    option.value = calendar;
    option.textContent = displayNames.of(calendar);
    select.appendChild(option);
  });

  return select;
}

const selector = buildCalendarSelector("en-US");
document.body.appendChild(selector);

Now the dropdown shows names like "Gregorian Calendar", "Islamic Calendar", and "Hebrew Calendar" instead of technical identifiers.

You can display calendar names in different languages by changing the locale:

const calendars = ["gregory", "islamic", "hebrew", "buddhist", "chinese"];

const englishNames = new Intl.DisplayNames(["en-US"], { type: "calendar" });
const frenchNames = new Intl.DisplayNames(["fr-FR"], { type: "calendar" });
const arabicNames = new Intl.DisplayNames(["ar-SA"], { type: "calendar" });

calendars.forEach(calendar => {
  console.log(`${calendar}:`);
  console.log(`  English: ${englishNames.of(calendar)}`);
  console.log(`  French: ${frenchNames.of(calendar)}`);
  console.log(`  Arabic: ${arabicNames.of(calendar)}`);
});

// Output:
// gregory:
//   English: Gregorian Calendar
//   French: calendrier grégorien
//   Arabic: التقويم الميلادي
// islamic:
//   English: Islamic Calendar
//   French: calendrier musulman
//   Arabic: التقويم الهجري
// ...

This allows users to see calendar names in their preferred language.

Checking if a specific calendar is supported

Before using a calendar in your application, check whether the JavaScript environment supports it. This prevents runtime errors and allows you to implement fallback behavior:

function isCalendarSupported(calendar) {
  const supported = Intl.supportedValuesOf("calendar");
  return supported.includes(calendar);
}

if (isCalendarSupported("islamic")) {
  const formatter = new Intl.DateTimeFormat("en-US", {
    calendar: "islamic",
    year: "numeric",
    month: "long",
    day: "numeric"
  });
  console.log(formatter.format(new Date()));
} else {
  console.log("Islamic calendar is not supported");
}

This pattern works for any calendar identifier. You can use it to show or hide calendar options in your user interface, or to fall back to a default calendar when the preferred one is unavailable.

Creating a reusable feature detection function

Build a generic function to check calendar support and handle missing calendars gracefully:

function getCalendarOrFallback(preferredCalendar, fallbackCalendar = "gregory") {
  const supported = Intl.supportedValuesOf("calendar");

  if (supported.includes(preferredCalendar)) {
    return preferredCalendar;
  }

  if (supported.includes(fallbackCalendar)) {
    return fallbackCalendar;
  }

  return supported[0];
}

const calendar = getCalendarOrFallback("islamic", "gregory");
const formatter = new Intl.DateTimeFormat("en-US", {
  calendar,
  year: "numeric",
  month: "long",
  day: "numeric"
});

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

This function tries to use the preferred calendar, falls back to the specified fallback calendar if the preferred one is unavailable, and ultimately returns the first available calendar if both are unsupported.

Filtering calendars for your application

Most applications do not need to support every calendar system. Filter the list to include only the calendars relevant to your users:

function getRelevantCalendars(allowedCalendars) {
  const supported = Intl.supportedValuesOf("calendar");
  return allowedCalendars.filter(calendar => supported.includes(calendar));
}

const allowedCalendars = ["gregory", "islamic", "hebrew", "buddhist"];
const availableCalendars = getRelevantCalendars(allowedCalendars);

console.log(availableCalendars);
// Output: ["gregory", "islamic", "hebrew", "buddhist"]
// (assuming all are supported in the current environment)

This ensures you only offer calendars that both meet your requirements and work in the user's browser.

You can combine this with calendar selection to create a focused user interface:

function buildFilteredCalendarSelector(allowedCalendars, locale = "en-US") {
  const supported = Intl.supportedValuesOf("calendar");
  const available = allowedCalendars.filter(cal => supported.includes(cal));
  const displayNames = new Intl.DisplayNames([locale], { type: "calendar" });

  const select = document.createElement("select");

  available.forEach(calendar => {
    const option = document.createElement("option");
    option.value = calendar;
    option.textContent = displayNames.of(calendar);
    select.appendChild(option);
  });

  return select;
}

const selector = buildFilteredCalendarSelector(
  ["gregory", "islamic", "hebrew", "buddhist"],
  "en-US"
);
document.body.appendChild(selector);

This creates a selector showing only the calendars you want to support, with human-readable names, guaranteed to work in the current environment.

Grouping calendars by category

For applications that support many calendars, group them by type or region to improve usability:

function groupCalendars() {
  const calendars = Intl.supportedValuesOf("calendar");

  const groups = {
    solar: ["gregory", "iso8601", "persian", "ethiopic", "coptic"],
    lunar: ["islamic", "islamic-civil", "islamic-rgsa", "islamic-tbla", "islamic-umalqura"],
    lunisolar: ["hebrew", "chinese", "dangi"],
    erasBased: ["japanese", "roc", "buddhist"],
    other: []
  };

  const grouped = {
    solar: [],
    lunar: [],
    lunisolar: [],
    erasBased: [],
    other: []
  };

  calendars.forEach(calendar => {
    let placed = false;

    for (const [group, members] of Object.entries(groups)) {
      if (members.includes(calendar)) {
        grouped[group].push(calendar);
        placed = true;
        break;
      }
    }

    if (!placed) {
      grouped.other.push(calendar);
    }
  });

  return grouped;
}

const grouped = groupCalendars();
console.log(grouped);
// Output:
// {
//   solar: ["gregory", "iso8601", "persian", "ethiopic", "coptic"],
//   lunar: ["islamic", "islamic-civil", "islamic-rgsa", ...],
//   lunisolar: ["hebrew", "chinese", "dangi"],
//   erasBased: ["japanese", "roc", "buddhist"],
//   other: ["ethioaa", "indian"]
// }

This organization helps users understand the characteristics of different calendar systems and find the one they need.

Handling unsupported environments

The Intl.supportedValuesOf() method was added to JavaScript in 2022. Older browsers do not support it. Check whether the method exists before using it:

function getCalendars() {
  if (typeof Intl.supportedValuesOf === "function") {
    return Intl.supportedValuesOf("calendar");
  }

  return ["gregory"];
}

const calendars = getCalendars();
console.log(calendars);

This returns the full list of supported calendars in modern browsers, and falls back to just the Gregorian calendar in older environments.

For better backward compatibility, provide a more complete fallback list:

function getCalendars() {
  if (typeof Intl.supportedValuesOf === "function") {
    return Intl.supportedValuesOf("calendar");
  }

  return [
    "buddhist",
    "chinese",
    "coptic",
    "ethiopic",
    "gregory",
    "hebrew",
    "indian",
    "islamic",
    "japanese",
    "persian",
    "roc"
  ];
}

This provides a reasonable set of calendars for older browsers, though you cannot guarantee all of them work in every environment.

Understanding the difference between calendar and locale

Calendar and locale are related but separate concepts. The locale determines the language and regional formatting conventions, while the calendar determines which calendar system to use.

A single locale can use multiple calendars. For example, Arabic speakers in Saudi Arabia typically use the Islamic calendar for religious purposes and the Gregorian calendar for civil purposes. You can format dates in Arabic using either calendar:

const date = new Date("2025-10-15");

const arabicGregorian = new Intl.DateTimeFormat("ar-SA", {
  calendar: "gregory",
  year: "numeric",
  month: "long",
  day: "numeric"
});

const arabicIslamic = new Intl.DateTimeFormat("ar-SA", {
  calendar: "islamic",
  year: "numeric",
  month: "long",
  day: "numeric"
});

console.log(arabicGregorian.format(date));
// Output: "١٥ أكتوبر ٢٠٢٥"

console.log(arabicIslamic.format(date));
// Output: "١٦ ربيع الآخر ١٤٤٧ هـ"

Both use Arabic text and numbering, but show different dates according to their respective calendars.

Conversely, you can format the same calendar in different languages:

const date = new Date("2025-10-15");

const englishIslamic = new Intl.DateTimeFormat("en-US", {
  calendar: "islamic",
  year: "numeric",
  month: "long",
  day: "numeric"
});

const arabicIslamic = new Intl.DateTimeFormat("ar-SA", {
  calendar: "islamic",
  year: "numeric",
  month: "long",
  day: "numeric"
});

console.log(englishIslamic.format(date));
// Output: "Rabi' II 16, 1447 AH"

console.log(arabicIslamic.format(date));
// Output: "١٦ ربيع الآخر ١٤٤٧ هـ"

Both show the Islamic date, but use different languages and number systems.

When to query available calendars

Query available calendars in these situations:

When building a calendar selection interface, call Intl.supportedValuesOf("calendar") to populate the options. This ensures you only show calendars that work in the current environment.

When implementing calendar-based features, check whether the required calendar is supported before using it. This prevents errors and allows graceful fallback to alternative calendars.

When storing user preferences, validate calendar selections against the supported list. This ensures saved preferences remain valid across different devices and browsers.

When migrating between environments, check calendar support in both the source and target environments. Calendar support can vary between browser versions, Node.js versions, and different JavaScript runtimes.

When loading calendar-dependent data, verify the calendar is available before attempting to parse or format dates. This prevents runtime errors when working with dates in specific calendar systems.