API Intl.DateTimeFormat

Formatea fechas y horas para cualquier configuración regional sin bibliotecas externas

Introducción

Las fechas se muestran de manera diferente en todo el mundo. El 15 de enero de 2024 aparece como 1/15/2024 en Estados Unidos, 15/1/2024 en el Reino Unido y 2024/1/15 en Japón. Los formatos de hora también varían. Los estadounidenses usan relojes de 12 horas con AM y PM, mientras que la mayor parte del mundo usa el formato de 24 horas.

Construir lógica de formateo de fechas manual para diferentes configuraciones regionales es complejo y propenso a errores. Necesitas manejar el orden de días y meses, separadores, formatos de hora, conversiones de zona horaria y casos especiales como calendarios no gregorianos.

La API Intl.DateTimeFormat resuelve este problema. Proporciona formateo de fecha y hora integrado y adaptado a la configuración regional en todos los navegadores modernos. No se requieren bibliotecas externas.

Uso básico

La forma más sencilla de formatear una fecha es crear una instancia de Intl.DateTimeFormat y llamar a su método format().

const date = new Date(2024, 0, 15, 14, 30);

const formatter = new Intl.DateTimeFormat("en-US");
formatter.format(date);
// "1/15/2024"

Cambia la configuración regional para ver diferentes convenciones de formateo.

const ukFormatter = new Intl.DateTimeFormat("en-GB");
ukFormatter.format(date);
// "15/01/2024"

const japanFormatter = new Intl.DateTimeFormat("ja-JP");
japanFormatter.format(date);
// "2024/1/15"

La misma fecha, formateada de tres maneras diferentes según las convenciones locales.

Comprender las configuraciones regionales

Una configuración regional es una cadena que identifica un idioma y preferencias regionales. El formato sigue el estándar BCP 47: código de idioma, opcionalmente seguido de un código de región.

Patrones comunes de configuración regional:

"en"      // English (generic)
"en-US"   // English (United States)
"en-GB"   // English (United Kingdom)
"es"      // Spanish (generic)
"es-MX"   // Spanish (Mexico)
"es-ES"   // Spanish (Spain)
"zh-CN"   // Chinese (China, Simplified)
"zh-TW"   // Chinese (Taiwan, Traditional)

Si omites el parámetro de configuración regional, el navegador usa la configuración regional predeterminada del usuario.

const formatter = new Intl.DateTimeFormat();
formatter.format(date);
// Output varies based on user's browser locale

También puedes proporcionar un array de configuraciones regionales. El navegador usa la primera configuración regional compatible.

const formatter = new Intl.DateTimeFormat(["es-MX", "es", "en"]);
// Uses Spanish (Mexico) if available, falls back to generic Spanish, then English

Descripción general de las opciones de formateo

El constructor Intl.DateTimeFormat acepta un objeto de opciones que controla qué aparece en la salida formateada. Hay dos enfoques para el formateo.

El primer enfoque usa atajos de estilo. Estos proporcionan un formateo rápido y convencional.

const formatter = new Intl.DateTimeFormat("en-US", {
  dateStyle: "full",
  timeStyle: "short"
});

formatter.format(date);
// "Monday, January 15, 2024 at 2:30 PM"

El segundo enfoque utiliza opciones de componentes. Estas proporcionan control granular sobre cada parte de la fecha.

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

formatter.format(date);
// "January 15, 2024 at 2:30 PM"

No puedes mezclar atajos de estilo con opciones de componentes. Elige un enfoque por formateador.

Atajos de estilo

Las opciones dateStyle y timeStyle proporcionan cuatro niveles de formato predefinidos.

La opción dateStyle formatea la parte de la fecha.

const date = new Date(2024, 0, 15);

const full = new Intl.DateTimeFormat("en-US", { dateStyle: "full" });
full.format(date);
// "Monday, January 15, 2024"

const long = new Intl.DateTimeFormat("en-US", { dateStyle: "long" });
long.format(date);
// "January 15, 2024"

const medium = new Intl.DateTimeFormat("en-US", { dateStyle: "medium" });
medium.format(date);
// "Jan 15, 2024"

const short = new Intl.DateTimeFormat("en-US", { dateStyle: "short" });
short.format(date);
// "1/15/24"

La opción timeStyle formatea la parte de la hora.

const date = new Date(2024, 0, 15, 14, 30, 45);

const full = new Intl.DateTimeFormat("en-US", { timeStyle: "full" });
full.format(date);
// "2:30:45 PM Eastern Standard Time"

const long = new Intl.DateTimeFormat("en-US", { timeStyle: "long" });
long.format(date);
// "2:30:45 PM EST"

const medium = new Intl.DateTimeFormat("en-US", { timeStyle: "medium" });
medium.format(date);
// "2:30:45 PM"

const short = new Intl.DateTimeFormat("en-US", { timeStyle: "short" });
short.format(date);
// "2:30 PM"

Combina ambas opciones para formatear fecha y hora juntas.

const formatter = new Intl.DateTimeFormat("en-US", {
  dateStyle: "medium",
  timeStyle: "short"
});

formatter.format(date);
// "Jan 15, 2024, 2:30 PM"

Los atajos de estilo se adaptan automáticamente a las convenciones locales.

const usFormatter = new Intl.DateTimeFormat("en-US", {
  dateStyle: "short",
  timeStyle: "short"
});
usFormatter.format(date);
// "1/15/24, 2:30 PM"

const deFormatter = new Intl.DateTimeFormat("de-DE", {
  dateStyle: "short",
  timeStyle: "short"
});
deFormatter.format(date);
// "15.1.24, 14:30"

El formato alemán utiliza puntos como separadores, invierte el orden de día y mes, y muestra la hora en formato de 24 horas. El formato americano utiliza barras, orden mes-primero, y hora en formato de 12 horas con AM/PM. Mismas opciones, salida diferente según la configuración regional.

Opciones de componentes

Las opciones de componentes proporcionan control preciso sobre qué se muestra y cómo. Cada opción especifica una parte de la fecha o la hora.

La opción year muestra el año.

const formatter = new Intl.DateTimeFormat("en-US", { year: "numeric" });
formatter.format(date);
// "2024"

const twoDigit = new Intl.DateTimeFormat("en-US", { year: "2-digit" });
twoDigit.format(date);
// "24"

La opción month muestra el mes en varios formatos.

const numeric = new Intl.DateTimeFormat("en-US", { month: "numeric" });
numeric.format(date);
// "1"

const twoDigit = new Intl.DateTimeFormat("en-US", { month: "2-digit" });
twoDigit.format(date);
// "01"

const long = new Intl.DateTimeFormat("en-US", { month: "long" });
long.format(date);
// "January"

const short = new Intl.DateTimeFormat("en-US", { month: "short" });
short.format(date);
// "Jan"

const narrow = new Intl.DateTimeFormat("en-US", { month: "narrow" });
narrow.format(date);
// "J"

La opción day muestra el día del mes.

const formatter = new Intl.DateTimeFormat("en-US", { day: "numeric" });
formatter.format(date);
// "15"

const twoDigit = new Intl.DateTimeFormat("en-US", { day: "2-digit" });
twoDigit.format(date);
// "15"

La opción weekday muestra el día de la semana.

const long = new Intl.DateTimeFormat("en-US", { weekday: "long" });
long.format(date);
// "Monday"

const short = new Intl.DateTimeFormat("en-US", { weekday: "short" });
short.format(date);
// "Mon"

const narrow = new Intl.DateTimeFormat("en-US", { weekday: "narrow" });
narrow.format(date);
// "M"

Combina múltiples opciones de componentes para crear formatos de fecha personalizados.

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

formatter.format(date);
// "Monday, January 15, 2024"

El navegador gestiona el espaciado y la puntuación según las convenciones de la configuración regional.

Formato de hora

Las opciones de componentes de hora controlan la visualización de horas, minutos y segundos.

const date = new Date(2024, 0, 15, 14, 30, 45);

const formatter = new Intl.DateTimeFormat("en-US", {
  hour: "numeric",
  minute: "numeric",
  second: "numeric"
});

formatter.format(date);
// "2:30:45 PM"

La opción hour12 controla la visualización de hora en formato de 12 horas frente a 24 horas.

const hour12 = new Intl.DateTimeFormat("en-US", {
  hour: "numeric",
  minute: "numeric",
  hour12: true
});
hour12.format(date);
// "2:30 PM"

const hour24 = new Intl.DateTimeFormat("en-US", {
  hour: "numeric",
  minute: "numeric",
  hour12: false
});
hour24.format(date);
// "14:30"

La opción hourCycle proporciona un control más preciso sobre la visualización de la hora. Existen cuatro opciones.

// h11: 0-11
const h11 = new Intl.DateTimeFormat("en-US", {
  hour: "numeric",
  hourCycle: "h11"
});
h11.format(new Date(2024, 0, 15, 0, 30));
// "0:30 AM"

// h12: 1-12
const h12 = new Intl.DateTimeFormat("en-US", {
  hour: "numeric",
  hourCycle: "h12"
});
h12.format(new Date(2024, 0, 15, 0, 30));
// "12:30 AM"

// h23: 0-23
const h23 = new Intl.DateTimeFormat("en-US", {
  hour: "numeric",
  hourCycle: "h23"
});
h23.format(new Date(2024, 0, 15, 0, 30));
// "0:30"

// h24: 1-24
const h24 = new Intl.DateTimeFormat("en-US", {
  hour: "numeric",
  hourCycle: "h24"
});
h24.format(new Date(2024, 0, 15, 0, 30));
// "24:30"

La diferencia importa a medianoche. El ciclo h11 usa 0, mientras que h12 usa 12. De manera similar, h23 usa 0, mientras que h24 usa 24.

La opción dayPeriod añade marcadores de periodo descriptivos para la hora en formato de 12 horas.

const morning = new Date(2024, 0, 15, 10, 30);
const afternoon = new Date(2024, 0, 15, 14, 30);
const night = new Date(2024, 0, 15, 22, 30);

const formatter = new Intl.DateTimeFormat("en-US", {
  hour: "numeric",
  minute: "numeric",
  dayPeriod: "long"
});

formatter.format(morning);
// "10:30 in the morning"

formatter.format(afternoon);
// "2:30 in the afternoon"

formatter.format(night);
// "10:30 at night"

La opción dayPeriod solo funciona con formatos de hora de 12 horas.

La opción fractionalSecondDigits muestra la precisión de subsegundos.

const date = new Date(2024, 0, 15, 14, 30, 45, 123);

const oneDigit = new Intl.DateTimeFormat("en-US", {
  hour: "numeric",
  minute: "numeric",
  second: "numeric",
  fractionalSecondDigits: 1
});
oneDigit.format(date);
// "2:30:45.1 PM"

const threeDigits = new Intl.DateTimeFormat("en-US", {
  hour: "numeric",
  minute: "numeric",
  second: "numeric",
  fractionalSecondDigits: 3
});
threeDigits.format(date);
// "2:30:45.123 PM"

Puedes especificar uno, dos o tres dígitos fraccionarios.

Gestión de zonas horarias

La opción timeZone convierte fechas a zonas horarias específicas.

const date = new Date("2024-01-15T14:30:00Z"); // UTC time

const newYork = new Intl.DateTimeFormat("en-US", {
  timeZone: "America/New_York",
  dateStyle: "full",
  timeStyle: "long"
});
newYork.format(date);
// "Monday, January 15, 2024 at 9:30:00 AM EST"

const tokyo = new Intl.DateTimeFormat("ja-JP", {
  timeZone: "Asia/Tokyo",
  dateStyle: "full",
  timeStyle: "long"
});
tokyo.format(date);
// "2024年1月15日月曜日 23:30:00 日本標準時"

const london = new Intl.DateTimeFormat("en-GB", {
  timeZone: "Europe/London",
  dateStyle: "full",
  timeStyle: "long"
});
london.format(date);
// "Monday, 15 January 2024 at 14:30:00 GMT"

El mismo momento en el tiempo se muestra de manera diferente según la zona horaria. Usa identificadores de zona horaria IANA como America/New_York, Europe/London o Asia/Tokyo.

La opción timeZoneName muestra el nombre de la zona horaria.

const formatter = new Intl.DateTimeFormat("en-US", {
  hour: "numeric",
  minute: "numeric",
  timeZone: "America/New_York",
  timeZoneName: "short"
});
formatter.format(date);
// "9:30 AM EST"

const long = new Intl.DateTimeFormat("en-US", {
  hour: "numeric",
  minute: "numeric",
  timeZone: "America/New_York",
  timeZoneName: "long"
});
long.format(date);
// "9:30 AM Eastern Standard Time"

const shortOffset = new Intl.DateTimeFormat("en-US", {
  hour: "numeric",
  minute: "numeric",
  timeZone: "America/New_York",
  timeZoneName: "shortOffset"
});
shortOffset.format(date);
// "9:30 AM GMT-5"

const longOffset = new Intl.DateTimeFormat("en-US", {
  hour: "numeric",
  minute: "numeric",
  timeZone: "America/New_York",
  timeZoneName: "longOffset"
});
longOffset.format(date);
// "9:30 AM GMT-05:00"

Los diferentes valores de timeZoneName proporcionan diferentes niveles de detalle.

Sistemas de calendario y sistemas de numeración

La opción calendar admite calendarios no gregorianos.

const date = new Date(2024, 0, 15);

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

const japanese = new Intl.DateTimeFormat("ja-JP", {
  calendar: "japanese",
  year: "numeric",
  month: "long",
  day: "numeric"
});
japanese.format(date);
// "令和6年1月15日"

const islamic = new Intl.DateTimeFormat("ar-SA", {
  calendar: "islamic",
  year: "numeric",
  month: "long",
  day: "numeric"
});
islamic.format(date);
// "٦ رجب ١٤٤٥"

const chinese = new Intl.DateTimeFormat("zh-CN", {
  calendar: "chinese",
  year: "numeric",
  month: "long",
  day: "numeric"
});
chinese.format(date);
// "2023甲辰年腊月初五"

La misma fecha se convierte a diferentes sistemas de calendario. Los calendarios disponibles incluyen gregory, japanese, islamic, islamic-umalqura, islamic-tbla, islamic-civil, islamic-rgsa, chinese, hebrew, indian, persian y otros.

La opción numberingSystem muestra los dígitos en diferentes sistemas de escritura.

const date = new Date(2024, 0, 15);

const western = new Intl.DateTimeFormat("en-US", {
  numberingSystem: "latn",
  year: "numeric",
  month: "numeric",
  day: "numeric"
});
western.format(date);
// "1/15/2024"

const arabic = new Intl.DateTimeFormat("en-US", {
  numberingSystem: "arab",
  year: "numeric",
  month: "numeric",
  day: "numeric"
});
arabic.format(date);
// "١‏/١٥‏/٢٠٢٤"

const devanagari = new Intl.DateTimeFormat("en-US", {
  numberingSystem: "deva",
  year: "numeric",
  month: "numeric",
  day: "numeric"
});
devanagari.format(date);
// "१/१५/२०२४"

const bengali = new Intl.DateTimeFormat("en-US", {
  numberingSystem: "beng",
  year: "numeric",
  month: "numeric",
  day: "numeric"
});
bengali.format(date);
// "১/১৫/২০২৪"

Los sistemas de numeración disponibles incluyen latn (dígitos occidentales), arab (dígitos arábigo-índicos), arabext (dígitos arábigo-índicos extendidos), beng (dígitos bengalíes), deva (dígitos devanagari) y muchos otros.

Formateo de rangos de fechas

El método formatRange() formatea un rango de fechas con omisión inteligente de información redundante.

const start = new Date(2024, 0, 15);
const end = new Date(2024, 0, 20);

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

formatter.formatRange(start, end);
// "January 15 – 20, 2024"

El formateador omite la información repetida. Ambas fechas están en enero de 2024, por lo que la salida solo incluye el mes y el año una vez.

Cuando el rango abarca diferentes meses, ambos se muestran.

const start = new Date(2024, 0, 15);
const end = new Date(2024, 1, 20);

formatter.formatRange(start, end);
// "January 15 – February 20, 2024"

Cuando el rango abarca diferentes años, se muestra toda la información.

const start = new Date(2024, 0, 15);
const end = new Date(2025, 1, 20);

formatter.formatRange(start, end);
// "January 15, 2024 – February 20, 2025"

El método formatRange() también funciona con rangos de tiempo.

const start = new Date(2024, 0, 15, 14, 30);
const end = new Date(2024, 0, 15, 16, 45);

const formatter = new Intl.DateTimeFormat("en-US", {
  month: "long",
  day: "numeric",
  hour: "numeric",
  minute: "numeric"
});

formatter.formatRange(start, end);
// "January 15, 2:30 – 4:45 PM"

La fecha se muestra una vez porque ambas horas ocurren en el mismo día.

Acceso a las partes formateadas

El método formatToParts() devuelve un array de objetos que representan cada parte de la fecha formateada. Esto permite una lógica de formateo personalizada.

const date = new Date(2024, 0, 15, 14, 30);

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

const parts = formatter.formatToParts(date);

Cada objeto del array tiene una propiedad type y value.

[
  { type: "month", value: "January" },
  { type: "literal", value: " " },
  { type: "day", value: "15" },
  { type: "literal", value: ", " },
  { type: "year", value: "2024" },
  { type: "literal", value: " at " },
  { type: "hour", value: "2" },
  { type: "literal", value: ":" },
  { type: "minute", value: "30" },
  { type: "literal", value: " " },
  { type: "dayPeriod", value: "PM" }
]

Puedes filtrar y manipular estas partes para construir formatos personalizados.

const dateParts = parts.filter(part =>
  ["month", "day", "year"].includes(part.type)
);

const dateString = dateParts.map(part => part.value).join("/");
// "January/15/2024"

El método formatRangeToParts() proporciona la misma funcionalidad para rangos de fechas.

const start = new Date(2024, 0, 15);
const end = new Date(2024, 0, 20);

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

const parts = formatter.formatRangeToParts(start, end);

Cada objeto de parte incluye una propiedad source que indica si proviene de la fecha de inicio o de fin.

[
  { type: "month", value: "January", source: "startRange" },
  { type: "literal", value: " ", source: "startRange" },
  { type: "day", value: "15", source: "startRange" },
  { type: "literal", value: " – ", source: "shared" },
  { type: "day", value: "20", source: "endRange" },
  { type: "literal", value: ", ", source: "shared" },
  { type: "year", value: "2024", source: "shared" }
]

Mejores prácticas

Reutiliza las instancias de formateador al formatear múltiples fechas con las mismas opciones. Crear un formateador implica negociación de locale y resolución de opciones, lo cual tiene un pequeño coste de rendimiento.

// Less efficient
dates.forEach(date => {
  const formatted = new Intl.DateTimeFormat("en-US").format(date);
  console.log(formatted);
});

// More efficient
const formatter = new Intl.DateTimeFormat("en-US");
dates.forEach(date => {
  const formatted = formatter.format(date);
  console.log(formatted);
});

Utiliza el locale del navegador del usuario cuando sea posible omitiendo el parámetro de locale. Esto respeta las preferencias del usuario.

const formatter = new Intl.DateTimeFormat();
// Uses browser locale automatically

Proporciona locales de respaldo al dirigirte a regiones específicas. Si el locale preferido no está disponible, el navegador utiliza la siguiente opción.

const formatter = new Intl.DateTimeFormat(["fr-CA", "fr", "en"]);
// Prefers French (Canada), falls back to French, then English

Utiliza atajos de estilo para visualizaciones comunes de fecha y hora. Se adaptan automáticamente a las convenciones del locale y requieren menos configuración.

const formatter = new Intl.DateTimeFormat("en-US", {
  dateStyle: "medium",
  timeStyle: "short"
});

Utiliza opciones de componente cuando necesites control preciso sobre el formato de salida.

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

Especifica siempre la zona horaria al mostrar horas a usuarios remotos o para eventos programados. Sin una zona horaria, las fechas se formatean en la zona horaria local del usuario, lo cual puede no coincidir con tu intención.

const formatter = new Intl.DateTimeFormat("en-US", {
  timeZone: "America/New_York",
  dateStyle: "full",
  timeStyle: "long"
});

Utiliza formatRange() para rangos de fechas en lugar de formatear cada fecha por separado y concatenarlas. El método maneja la omisión inteligente de información redundante.

// Less clear
const startFormatted = formatter.format(start);
const endFormatted = formatter.format(end);
const range = `${startFormatted} to ${endFormatted}`;

// Better
const range = formatter.formatRange(start, end);

Verifica la compatibilidad del navegador para funciones avanzadas como dayPeriod, fractionalSecondDigits y ciertos valores de timeZoneName. Todos los navegadores modernos admiten la funcionalidad principal, pero las opciones más nuevas pueden requerir respaldos para navegadores más antiguos.