Cómo formatear horas en la configuración regional del usuario
Usa JavaScript para mostrar horas según las convenciones regionales de cada usuario
Introducción
Las horas se muestran de manera diferente en todo el mundo. Los estadounidenses normalmente ven las 3:30 PM como 3:30 PM, mientras que la mayoría de los europeos esperan 15:30. Cuando codificas un formato de hora de forma estática, asumes que todos los usuarios siguen la misma convención.
Mostrar horas en un formato poco familiar crea confusión. Un usuario acostumbrado al formato de 24 horas que ve 3:30 PM debe convertirlo mentalmente para entender si representa la mañana o la tarde. Esta carga cognitiva se multiplica con cada hora en tu aplicación.
JavaScript proporciona la API Intl.DateTimeFormat para manejar el formato de hora automáticamente. Esta lección explica por qué los formatos de hora varían entre culturas, cómo funciona la API y cómo formatear correctamente las horas para cualquier configuración regional.
Por qué los formatos de hora varían según la configuración regional
Diferentes regiones desarrollaron distintas convenciones para mostrar las horas. Estas convenciones reflejan prácticas históricas, sistemas educativos y preferencias culturales. Ningún formato es universal.
En Estados Unidos, Canadá, Australia y Filipinas, las horas utilizan el formato de 12 horas con indicadores AM y PM. Las 3:30 de la tarde aparecen como 3:30 PM.
En la mayoría de los países europeos, América Latina y Asia, las horas utilizan el formato de 24 horas sin indicadores AM o PM. La misma hora aparece como 15:30.
El carácter separador entre horas y minutos también varía. Los países de habla inglesa utilizan dos puntos, mientras que algunas configuraciones regionales utilizan puntos u otros signos de puntuación.
La forma en que aparecen AM y PM también difiere. El inglés usa AM y PM, el español usa a.m. y p.m., y algunas configuraciones regionales colocan estos indicadores antes de la hora en lugar de después.
Cuando muestras horas, necesitas adaptarte a las expectativas del usuario tanto en el formato de hora como en las convenciones de formato específicas.
Uso de Intl.DateTimeFormat para formatear horas
El constructor Intl.DateTimeFormat crea un formateador que aplica convenciones específicas del idioma. Para formatear horas, pasa un identificador de idioma como primer argumento y especifica las opciones relacionadas con el tiempo en el segundo argumento.
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric'
});
const date = new Date('2025-03-15T15:30:00');
console.log(formatter.format(date));
// Resultado: "3:30 PM"
Esto crea un formateador para inglés estadounidense que muestra horas y minutos. Las opciones hour y minute indican al formateador que incluya estos componentes. El método format() convierte el objeto Date en una cadena con el formato apropiado.
El constructor Date acepta una cadena de fecha y hora ISO 8601 como 2025-03-15T15:30:00. Esto crea un objeto Date que representa las 3:30 PM del 15 de marzo de 2025. El formateador luego convierte esto en una cadena de tiempo específica del idioma.
Formateo de la misma hora para diferentes idiomas
Puedes formatear la misma hora para diferentes idiomas cambiando el identificador de idioma pasado al constructor.
const date = new Date('2025-03-15T15:30:00');
const usFormatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric'
});
console.log(usFormatter.format(date));
// Resultado: "3:30 PM"
const gbFormatter = new Intl.DateTimeFormat('en-GB', {
hour: 'numeric',
minute: 'numeric'
});
console.log(gbFormatter.format(date));
// Resultado: "15:30"
const deFormatter = new Intl.DateTimeFormat('de-DE', {
hour: 'numeric',
minute: 'numeric'
});
console.log(deFormatter.format(date));
// Resultado: "15:30"
const frFormatter = new Intl.DateTimeFormat('fr-FR', {
hour: 'numeric',
minute: 'numeric'
});
console.log(frFormatter.format(date));
// Resultado: "15:30"
Cada formateador aplica diferentes convenciones. El formateador estadounidense utiliza el formato de 12 horas con AM/PM. Los formateadores británico, alemán y francés utilizan el formato de 24 horas sin indicadores AM/PM.
No necesitas saber qué formato utiliza cada idioma. La API maneja estos detalles automáticamente según el identificador de idioma.
Incluir segundos en la visualización de la hora
Puedes añadir la opción second para mostrar los segundos junto con las horas y minutos.
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric',
second: 'numeric'
});
const date = new Date('2025-03-15T15:30:45');
console.log(formatter.format(date));
// Output: "3:30:45 PM"
La opción second funciona de la misma manera que hour y minute. Configúrala como 'numeric' para incluir segundos en la salida.
Controlar el relleno de dígitos con 2-digit
Las opciones hour, minute y second aceptan dos valores: 'numeric' y '2-digit'. El valor 'numeric' muestra dígitos sin relleno, mientras que '2-digit' siempre muestra dos dígitos con ceros a la izquierda.
const date = new Date('2025-03-15T09:05:03');
const numericFormatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric',
second: 'numeric'
});
console.log(numericFormatter.format(date));
// Output: "9:05:03 AM"
const twoDigitFormatter = new Intl.DateTimeFormat('en-US', {
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
});
console.log(twoDigitFormatter.format(date));
// Output: "09:05:03 AM"
El formateador numérico muestra 9:05:03 AM con un solo dígito para la hora. El formateador de dos dígitos muestra 09:05:03 AM con un cero a la izquierda para la hora. Ambos muestran dos dígitos para minutos y segundos porque estos valores normalmente se rellenan independientemente de la configuración.
Forzar formato de 12 horas o 24 horas
Por defecto, la API utiliza el formato de hora preferido por la configuración regional. Puedes anular esto con la opción hour12.
const date = new Date('2025-03-15T15:30:00');
const hour12Formatter = new Intl.DateTimeFormat('en-GB', {
hour: 'numeric',
minute: 'numeric',
hour12: true
});
console.log(hour12Formatter.format(date));
// Output: "3:30 pm"
const hour24Formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric',
hour12: false
});
console.log(hour24Formatter.format(date));
// Output: "15:30"
Configurar hour12: true fuerza el formato de 12 horas incluso para configuraciones regionales que normalmente utilizan el formato de 24 horas. Configurar hour12: false fuerza el formato de 24 horas incluso para configuraciones regionales que normalmente utilizan el formato de 12 horas.
La configuración regional sigue determinando otros detalles de formato como puntuación y espaciado. El formateador del Reino Unido con hour12: true muestra 3:30 pm con pm en minúsculas, mientras que un formateador de EE. UU. mostraría 3:30 PM con PM en mayúsculas.
Formateo de horas para la configuración regional del usuario
En lugar de codificar una configuración regional específica, puedes utilizar el idioma preferido del usuario desde el navegador. La propiedad navigator.language devuelve la preferencia de idioma principal del usuario.
const userLocale = navigator.language;
const formatter = new Intl.DateTimeFormat(userLocale, {
hour: 'numeric',
minute: 'numeric'
});
const date = new Date('2025-03-15T15:30:00');
console.log(formatter.format(date));
// La salida varía según la configuración regional del usuario
// Para en-US: "3:30 PM"
// Para en-GB: "15:30"
// Para de-DE: "15:30"
// Para fr-FR: "15:30"
Este enfoque muestra las horas de acuerdo con las expectativas de cada usuario sin requerir que seleccionen manualmente una configuración regional. El navegador proporciona la preferencia de idioma y la API Intl aplica las convenciones de formato apropiadas.
También puedes pasar el array completo de idiomas preferidos para habilitar el comportamiento de respaldo.
const formatter = new Intl.DateTimeFormat(navigator.languages, {
hour: 'numeric',
minute: 'numeric'
});
const date = new Date('2025-03-15T15:30:00');
console.log(formatter.format(date));
La API utiliza la primera configuración regional que admite del array. Esto proporciona un mejor manejo de respaldo cuando la preferencia principal del usuario no está disponible.
Creación de horas para formatear
Puedes crear objetos Date con información de hora de varias maneras. El enfoque más confiable es utilizar cadenas de fecha y hora ISO 8601.
const time1 = new Date('2025-03-15T09:00:00');
const time2 = new Date('2025-03-15T15:30:00');
const time3 = new Date('2025-03-15T23:45:30');
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric'
});
console.log(formatter.format(time1));
// Salida: "9:00 AM"
console.log(formatter.format(time2));
// Salida: "3:30 PM"
console.log(formatter.format(time3));
// Salida: "11:45 PM"
Las cadenas de fecha y hora ISO 8601 utilizan el formato YYYY-MM-DDTHH:MM:SS. La T separa la fecha de la hora. Este formato es inequívoco y funciona de manera consistente en todas las configuraciones regionales y zonas horarias.
Formateo de horas a partir de marcas de tiempo
También puedes crear objetos Date a partir de marcas de tiempo Unix. Una marca de tiempo Unix representa el número de milisegundos desde el 1 de enero de 1970 UTC.
const timestamp = 1710515400000; // 15 de marzo de 2025 a las 3:30 PM
const date = new Date(timestamp);
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric'
});
console.log(formatter.format(date));
// Salida: "3:30 PM"
Este enfoque funciona cuando recibes marcas de tiempo desde APIs, bases de datos u otros sistemas que representan tiempos como números.
También puedes pasar la marca de tiempo directamente al método format() sin crear primero un objeto Date.
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric'
});
const timestamp = 1710515400000;
console.log(formatter.format(timestamp));
// Salida: "3:30 PM"
La API acepta tanto objetos Date como marcas de tiempo. Utiliza el enfoque que mejor se adapte a tu código.
Formateo de la hora actual
Para formatear la hora actual, crea un objeto Date sin argumentos. Esto crea un objeto Date que representa el momento actual.
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric',
second: 'numeric'
});
const now = new Date();
console.log(formatter.format(now));
// Salida: "3:45:12 PM" (o la hora actual cuando se ejecuta)
También puedes pasar Date.now() directamente, que devuelve la marca de tiempo actual como un número.
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric',
second: 'numeric'
});
console.log(formatter.format(Date.now()));
// Salida: "3:45:12 PM" (o la hora actual cuando se ejecuta)
Ambos enfoques producen resultados idénticos.
Reutilización de formateadores para mejorar el rendimiento
Crear una nueva instancia de Intl.DateTimeFormat implica cargar datos de localización y procesar opciones. Cuando necesites formatear múltiples horas con la misma configuración regional y ajustes, crea el formateador una vez y reutilízalo.
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric'
});
const times = [
new Date('2025-03-15T09:00:00'),
new Date('2025-03-15T12:30:00'),
new Date('2025-03-15T18:45:00')
];
times.forEach(time => {
console.log(formatter.format(time));
});
// Salida:
// "9:00 AM"
// "12:30 PM"
// "6:45 PM"
Este enfoque es más eficiente que crear un nuevo formateador para cada hora. La diferencia de rendimiento se vuelve significativa cuando se formatean arrays con cientos o miles de valores de tiempo.
Formateo de horas en plantillas
Puedes usar Intl.DateTimeFormat en cualquier lugar donde muestres horas a los usuarios. Esto incluye insertar horas formateadas en plantillas HTML, mostrar horas en tablas o mostrar marcas de tiempo en interfaces de usuario.
const formatter = new Intl.DateTimeFormat(navigator.language, {
hour: 'numeric',
minute: 'numeric'
});
const eventStart = new Date('2025-03-15T14:00:00');
const eventEnd = new Date('2025-03-15T16:30:00');
document.getElementById('start-time').textContent = formatter.format(eventStart);
document.getElementById('end-time').textContent = formatter.format(eventEnd);
Las cadenas formateadas funcionan como cualquier otro valor de cadena. Puedes insertarlas en contenido de texto, atributos o cualquier otro contexto donde muestres información a los usuarios.