Obtener lista de sistemas de calendario disponibles

Descubre qué sistemas de calendario admite tu entorno JavaScript

Introducción

Al crear aplicaciones para una audiencia global, los usuarios a menudo necesitan ver las fechas en su sistema de calendario preferido. Aunque puedas estar familiarizado con el calendario gregoriano utilizado en la mayoría de los países occidentales, muchas culturas utilizan sistemas de calendario completamente diferentes como el calendario islámico Hijri, el calendario hebreo o el calendario budista.

Para permitir que los usuarios seleccionen su calendario preferido, necesitas saber qué sistemas de calendario admite el entorno JavaScript. En lugar de mantener una lista codificada que queda obsoleta o incluye valores no admitidos, JavaScript proporciona un método para descubrir los sistemas de calendario disponibles en tiempo de ejecución.

El método Intl.supportedValuesOf() con el parámetro "calendar" devuelve un array de todos los identificadores de sistemas de calendario admitidos por el entorno actual. Esto garantiza que tu aplicación solo ofrezca opciones de calendario que funcionen correctamente.

Qué son los sistemas de calendario

Los sistemas de calendario son diferentes métodos de organizar y contar el tiempo. Aunque todos los calendarios rastrean días, meses y años, utilizan reglas diferentes para calcular cuándo comienza un año, cuánto duran los meses y cómo contabilizar los ciclos astronómicos.

El calendario gregoriano, introducido en 1582, es el calendario civil más utilizado. Utiliza un año solar de aproximadamente 365,25 días, dividido en 12 meses, con años bisiestos añadidos cada cuatro años (con excepciones para los años seculares).

Otros sistemas de calendario siguen reglas diferentes. El calendario islámico es puramente lunar, con meses que siguen las fases de la luna. Esto significa que el año islámico es aproximadamente 11 días más corto que un año solar, lo que hace que las fechas islámicas se desplacen a través de las estaciones con el tiempo. Los calendarios hebreo y chino son lunisolares, combinando meses lunares con ajustes para mantener el calendario sincronizado con el año solar.

Cuando formateas fechas en JavaScript, el sistema de calendario determina qué números de año, mes y día aparecen. El mismo momento en el tiempo tiene diferentes representaciones de fecha en diferentes sistemas de calendario.

Usar Intl.supportedValuesOf para obtener sistemas de calendario

El método Intl.supportedValuesOf() acepta un parámetro de cadena que especifica qué tipo de valores devolver. Para obtener sistemas de calendario, pasa "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"]

El método devuelve un array de cadenas que representan identificadores de calendario. Estos identificadores siguen el estándar Unicode CLDR (Common Locale Data Repository), que proporciona una forma consistente de referenciar sistemas de calendario en diferentes plataformas y lenguajes de programación.

El array devuelto tiene estas características:

  • Los valores están ordenados en orden alfabético ascendente
  • Se eliminan los valores duplicados
  • Cada identificador usa letras minúsculas y guiones
  • La lista incluye todos los sistemas de calendario compatibles con la implementación de JavaScript

Diferentes navegadores y entornos de JavaScript admiten diferentes conjuntos de calendarios, aunque todos los navegadores modernos admiten un conjunto básico de calendarios comunes.

Comprender los identificadores de calendario

Cada identificador de calendario representa un sistema de calendario específico utilizado por una o más culturas. Estos son los identificadores más comunes:

El identificador "gregory" representa el calendario gregoriano, el calendario civil estándar utilizado en la mayoría de los países. Este es el calendario que usas en la vida cotidiana si vives en Estados Unidos, Europa o la mayoría de las otras partes del mundo.

El identificador "buddhist" representa el calendario budista tailandés, que usa la misma estructura de mes y día que el calendario gregoriano pero cuenta los años desde el nacimiento de Buda (543 a. C. en el calendario gregoriano). El año 2025 en el calendario gregoriano es el año 2568 en el calendario budista.

El identificador "chinese" representa el calendario chino tradicional, un calendario lunisolar donde los meses siguen las fases de la luna y los años se alinean con el período orbital de Júpiter. El calendario chino se utiliza para determinar festividades tradicionales como el Año Nuevo Chino.

El identificador "islamic" representa el calendario islámico Hijri, un calendario puramente lunar con 12 meses de 29 o 30 días. Los años se cuentan desde la Hégira, cuando Mahoma emigró de La Meca a Medina en el año 622 d. C.

El identificador "hebrew" representa el calendario hebreo, un calendario lunisolar utilizado para las observancias religiosas judías. Cuenta los años desde una fecha de creación tradicional (3761 a. C. en el calendario gregoriano).

El identificador "japanese" representa el calendario japonés, que utiliza la misma estructura de mes y día que el calendario gregoriano pero divide el tiempo en eras basadas en el emperador reinante. La era actual es Reiwa, que comenzó en 2019.

El identificador "persian" representa el calendario Solar Hijri utilizado en Irán y Afganistán. Es un calendario solar con años contados desde la Hégira, lo que lo hace diferente del calendario islámico lunar.

Los identificadores adicionales incluyen "coptic" (calendario copto ortodoxo), "dangi" (calendario coreano tradicional), "ethiopic" (calendario etíope), "indian" (calendario nacional indio) y "roc" (calendario de la República de China utilizado en Taiwán).

Algunos identificadores tienen variantes como "islamic-civil", "islamic-rgsa", "islamic-tbla" y "islamic-umalqura", que representan diferentes métodos de cálculo para el calendario islámico.

El identificador "iso8601" representa el calendario ISO 8601, que es esencialmente el calendario gregoriano pero siempre utiliza el calendario gregoriano proléptico (extendiendo el calendario gregoriano hacia atrás antes de su introducción en 1582).

Ver los sistemas de calendario en acción

Para entender cómo los sistemas de calendario afectan el formato de fechas, formatea la misma fecha usando diferentes calendarios:

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"

El mismo objeto Date de JavaScript representa el mismo momento en el tiempo, pero cada sistema de calendario expresa ese momento con diferentes valores de año, mes y día. La fecha gregoriana 15 de octubre de 2025 corresponde a Rabi' II 16, 1447 en el calendario islámico, Tishrei 23, 5786 en el calendario hebreo y 15 de octubre de 2568 en el calendario budista.

Esto demuestra por qué necesitas especificar qué sistema de calendario usar al formatear fechas para usuarios que siguen diferentes calendarios.

Construir un selector de calendario

Al crear interfaces de usuario que permiten a los usuarios elegir su calendario preferido, consulta los calendarios disponibles y construye un selector dinámicamente:

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

Esto crea un menú desplegable que contiene todos los calendarios compatibles. Sin embargo, los identificadores técnicos como "gregory" y "islamic" no son fáciles de usar. Los usuarios necesitan ver nombres descriptivos en su propio idioma.

Mostrar nombres de calendario legibles

La API Intl.DisplayNames convierte identificadores de calendario en nombres legibles. Úsala para crear un mejor selector de calendario:

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

Ahora el menú desplegable muestra nombres como "Calendario gregoriano", "Calendario islámico" y "Calendario hebreo" en lugar de identificadores técnicos.

Puedes mostrar nombres de calendario en diferentes idiomas cambiando la configuración regional:

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: التقويم الهجري
// ...

Esto permite a los usuarios ver nombres de calendario en su idioma preferido.

Verificar si un calendario específico es compatible

Antes de usar un calendario en tu aplicación, verifica si el entorno de JavaScript lo admite. Esto previene errores en tiempo de ejecución y te permite implementar un comportamiento alternativo:

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

Este patrón funciona para cualquier identificador de calendario. Puedes usarlo para mostrar u ocultar opciones de calendario en tu interfaz de usuario, o para recurrir a un calendario predeterminado cuando el preferido no esté disponible.

Crear una función reutilizable de detección de características

Construye una función genérica para verificar la compatibilidad de calendarios y manejar calendarios faltantes de forma elegante:

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

Esta función intenta usar el calendario preferido, recurre al calendario de respaldo especificado si el preferido no está disponible y, en última instancia, devuelve el primer calendario disponible si ambos no son compatibles.

Filtrar calendarios para tu aplicación

La mayoría de las aplicaciones no necesitan admitir todos los sistemas de calendario. Filtra la lista para incluir solo los calendarios relevantes para tus usuarios:

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)

Esto garantiza que solo ofrezcas calendarios que cumplan con tus requisitos y funcionen en el navegador del usuario.

Puedes combinar esto con la selección de calendario para crear una interfaz de usuario enfocada:

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

Esto crea un selector que muestra solo los calendarios que deseas admitir, con nombres legibles para humanos, garantizados para funcionar en el entorno actual.

Agrupar calendarios por categoría

Para aplicaciones que admiten muchos calendarios, agrúpalos por tipo o región para mejorar la usabilidad:

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"]
// }

Esta organización ayuda a los usuarios a comprender las características de diferentes sistemas de calendario y encontrar el que necesitan.

Manejar entornos no compatibles

El método Intl.supportedValuesOf() se agregó a JavaScript en 2022. Los navegadores más antiguos no lo admiten. Verifica si el método existe antes de usarlo:

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

  return ["gregory"];
}

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

Esto devuelve la lista completa de calendarios compatibles en navegadores modernos y recurre solo al calendario gregoriano en entornos más antiguos.

Para una mejor compatibilidad con versiones anteriores, proporciona una lista de respaldo más completa:

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

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

Esto proporciona un conjunto razonable de calendarios para navegadores más antiguos, aunque no puedes garantizar que todos funcionen en cada entorno.

Comprender la diferencia entre calendario y configuración regional

El calendario y la configuración regional son conceptos relacionados pero separados. La configuración regional determina el idioma y las convenciones de formato regional, mientras que el calendario determina qué sistema de calendario utilizar.

Una sola configuración regional puede utilizar múltiples calendarios. Por ejemplo, los hablantes de árabe en Arabia Saudita suelen utilizar el calendario islámico para fines religiosos y el calendario gregoriano para fines civiles. Puedes formatear fechas en árabe utilizando cualquiera de los dos calendarios:

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

Ambos utilizan texto y numeración árabe, pero muestran fechas diferentes según sus respectivos calendarios.

Por el contrario, puedes formatear el mismo calendario en diferentes idiomas:

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

Ambos muestran la fecha islámica, pero utilizan diferentes idiomas y sistemas numéricos.

Cuándo consultar los calendarios disponibles

Consulta los calendarios disponibles en estas situaciones:

Al crear una interfaz de selección de calendario, llama a Intl.supportedValuesOf("calendar") para completar las opciones. Esto garantiza que solo muestres calendarios que funcionen en el entorno actual.

Al implementar funciones basadas en calendario, verifica si el calendario requerido es compatible antes de utilizarlo. Esto previene errores y permite un respaldo elegante a calendarios alternativos.

Al almacenar preferencias de usuario, valida las selecciones de calendario contra la lista de compatibles. Esto garantiza que las preferencias guardadas permanezcan válidas en diferentes dispositivos y navegadores.

Al migrar entre entornos, verifica la compatibilidad del calendario tanto en el entorno de origen como en el de destino. La compatibilidad del calendario puede variar entre versiones de navegadores, versiones de Node.js y diferentes entornos de ejecución de JavaScript.

Al cargar datos dependientes del calendario, verifica que el calendario esté disponible antes de intentar analizar o formatear fechas. Esto previene errores en tiempo de ejecución al trabajar con fechas en sistemas de calendario específicos.