API Intl.DurationFormat
Formatea duraciones de tiempo en JavaScript con localización automática
Introducción
Cuando muestras cuánto tiempo tarda algo, necesitas formatear valores de duración para los usuarios. Un reproductor de vídeo muestra la duración, una reserva de vuelo muestra el tiempo de viaje, una app de fitness muestra la duración del entrenamiento. Sin localización, podrías escribir código como este:
const hours = 1;
const minutes = 46;
const seconds = 40;
const duration = `${hours}h ${minutes}m ${seconds}s`;
Esto produce "1h 46m 40s" para todos los usuarios independientemente del idioma. Los usuarios franceses ven "1h 46m 40s" cuando esperan "1 h 46 min 40 s". Los usuarios alemanes ven las mismas abreviaturas en inglés. Los usuarios españoles no obtienen la conjunción "y" entre unidades.
La API Intl.DurationFormat resuelve esto. Formatea duraciones de tiempo según el idioma del usuario y las convenciones culturales sin bibliotecas externas ni construcción manual de cadenas.
const duration = { hours: 1, minutes: 46, seconds: 40 };
new Intl.DurationFormat('fr-FR', { style: 'short' }).format(duration);
// "1 h, 46 min et 40 s"
El formateador maneja automáticamente abreviaturas, conjunciones, orden de palabras y espaciado para cualquier configuración regional.
Qué son las duraciones
Una duración representa un intervalo de tiempo, no un punto en el tiempo. Las fechas y horas marcan cuándo ocurre algo. Las duraciones miden cuánto tiempo tarda algo.
Esta distinción importa para el formateo. Las fechas involucran calendarios, zonas horarias y reglas históricas. Las duraciones son más simples: miden tiempo transcurrido en unidades estándar sin contexto de calendario.
La API Intl.DurationFormat maneja duraciones. La API Intl.DateTimeFormat maneja fechas y horas. Usa la herramienta correcta para cada trabajo.
Crear un formateador de duración
El constructor toma una configuración regional y un objeto de opciones. La configuración regional determina el idioma de salida. Las opciones controlan el estilo de formateo y la visualización de unidades.
const formatter = new Intl.DurationFormat('en', { style: 'long' });
Llama a format() con un objeto de duración. El objeto contiene propiedades numéricas para unidades de tiempo. Solo incluye las unidades que quieres mostrar.
const duration = { hours: 2, minutes: 30 };
formatter.format(duration);
// "2 hours and 30 minutes"
La API admite estas unidades de tiempo: years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds. Usa las unidades que coincidan con tus datos.
Elige un estilo de formato
La opción style controla la densidad de salida. Hay cuatro estilos disponibles: long, short, narrow y digital.
El estilo largo usa palabras completas. Úsalo para prosa y accesibilidad.
const duration = { hours: 1, minutes: 46, seconds: 40 };
new Intl.DurationFormat('en', { style: 'long' }).format(duration);
// "1 hour, 46 minutes and 40 seconds"
El estilo corto usa abreviaturas comunes. Úsalo cuando el espacio es limitado pero la legibilidad importa.
new Intl.DurationFormat('en', { style: 'short' }).format(duration);
// "1 hr, 46 min and 40 sec"
El estilo estrecho usa caracteres mínimos. Úsalo para pantallas compactas como interfaces móviles.
new Intl.DurationFormat('en', { style: 'narrow' }).format(duration);
// "1h 46m 40s"
El estilo digital produce salida similar a un temporizador con dos puntos. Úsalo para reproductores multimedia y pantallas de cuenta regresiva.
new Intl.DurationFormat('en', { style: 'digital' }).format(duration);
// "1:46:40"
Localización en diferentes idiomas
La misma duración se formatea de manera diferente en cada idioma. La API maneja toda la localización automáticamente.
const duration = { hours: 1, minutes: 46, seconds: 40 };
new Intl.DurationFormat('en', { style: 'long' }).format(duration);
// "1 hour, 46 minutes and 40 seconds"
new Intl.DurationFormat('fr', { style: 'long' }).format(duration);
// "1 heure, 46 minutes et 40 secondes"
new Intl.DurationFormat('de', { style: 'long' }).format(duration);
// "1 Stunde, 46 Minuten und 40 Sekunden"
new Intl.DurationFormat('es', { style: 'long' }).format(duration);
// "1 hora, 46 minutos y 40 segundos"
new Intl.DurationFormat('ja', { style: 'long' }).format(duration);
// "1時間46分40秒"
Observa cómo cada locale usa diferentes palabras, abreviaturas y conjunciones. El francés usa "et", el alemán usa "und", el español usa "y", el japonés no usa conjunciones. La API conoce estas reglas.
Los estilos corto y estrecho también se localizan correctamente.
new Intl.DurationFormat('fr', { style: 'short' }).format(duration);
// "1 h, 46 min et 40 s"
new Intl.DurationFormat('de', { style: 'narrow' }).format(duration);
// "1 Std. 46 Min. 40 Sek."
Construye objetos de duración a partir de cálculos de tiempo
Los objetos de duración son objetos JavaScript simples con propiedades de unidades de tiempo. Créalos a partir de cualquier cálculo de tiempo.
Convierte milisegundos a unidades de duración dividiendo por los factores apropiados.
const milliseconds = 6400000; // 1 hour, 46 minutes, 40 seconds
const hours = Math.floor(milliseconds / 3600000);
const minutes = Math.floor((milliseconds % 3600000) / 60000);
const seconds = Math.floor((milliseconds % 60000) / 1000);
const duration = { hours, minutes, seconds };
new Intl.DurationFormat('en', { style: 'short' }).format(duration);
// "1 hr, 46 min and 40 sec"
Calcula la duración a partir de dos fechas restando timestamps.
const start = new Date('2025-01-01T10:00:00');
const end = new Date('2025-01-01T11:46:40');
const diffMs = end - start;
const hours = Math.floor(diffMs / 3600000);
const minutes = Math.floor((diffMs % 3600000) / 60000);
const seconds = Math.floor((diffMs % 60000) / 1000);
const duration = { hours, minutes, seconds };
Incluye solo las unidades que necesites. Omite valores cero a menos que quieras que se muestren.
const duration = { minutes: 5, seconds: 30 };
new Intl.DurationFormat('en', { style: 'long' }).format(duration);
// "5 minutes and 30 seconds"
Controlar qué unidades aparecen
Por defecto, el formateador muestra todas las unidades que proporcionas en el objeto de duración. Controla la visualización de unidades con el objeto de opciones.
Especifica el estilo de visualización para cada unidad individualmente. Las opciones son long, short, narrow, numeric y 2-digit.
const duration = { hours: 1, minutes: 5, seconds: 3 };
new Intl.DurationFormat('en', {
hours: 'long',
minutes: 'numeric',
seconds: '2-digit'
}).format(duration);
// "1 hour, 5:03"
El estilo numeric muestra el número sin etiquetas. El estilo 2-digit añade relleno de ceros. Usa estos para visualizaciones compactas que mezclan texto y números.
Oculta unidades omitiéndolas tanto del objeto de duración como de las opciones.
const duration = { hours: 2, minutes: 30 };
new Intl.DurationFormat('en', { style: 'short' }).format(duration);
// "2 hr and 30 min"
El estilo digital requiere que todas las unidades desde la mayor hasta la menor estén presentes o configuradas explícitamente.
const duration = { minutes: 5, seconds: 30 };
new Intl.DurationFormat('en', { style: 'digital' }).format(duration);
// "5:30"
Formatear duraciones de reproductores de vídeo
Los reproductores de vídeo muestran la duración en los controles. Usa el estilo narrow o digital para una visualización compacta.
function formatVideoDuration(seconds) {
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
const secs = Math.floor(seconds % 60);
const duration = hours > 0
? { hours, minutes, seconds: secs }
: { minutes, seconds: secs };
const locale = navigator.language;
return new Intl.DurationFormat(locale, { style: 'digital' }).format(duration);
}
formatVideoDuration(6400); // "1:46:40"
formatVideoDuration(330); // "5:30"
Esto maneja tanto vídeos cortos como largos incluyendo las horas condicionalmente.
Formatear tiempos de vuelo y viaje
Las interfaces de reserva de viajes muestran la duración del trayecto. Usa el estilo short para legibilidad en espacios limitados.
function formatFlightDuration(departureDate, arrivalDate, locale) {
const diffMs = arrivalDate - departureDate;
const hours = Math.floor(diffMs / 3600000);
const minutes = Math.floor((diffMs % 3600000) / 60000);
const duration = { hours, minutes };
return new Intl.DurationFormat(locale, { style: 'short' }).format(duration);
}
const departure = new Date('2025-06-15T10:30:00');
const arrival = new Date('2025-06-15T18:45:00');
formatFlightDuration(departure, arrival, 'en');
// "8 hr and 15 min"
formatFlightDuration(departure, arrival, 'fr');
// "8 h et 15 min"
Formatear duraciones de entrenamientos y actividades
Las aplicaciones de fitness rastrean la duración del ejercicio. Usa el estilo long para resúmenes de sesión y el estilo narrow para vistas de lista.
function formatWorkoutDuration(startTime, endTime, locale) {
const diffMs = endTime - startTime;
const hours = Math.floor(diffMs / 3600000);
const minutes = Math.floor((diffMs % 3600000) / 60000);
const duration = hours > 0
? { hours, minutes }
: { minutes };
return new Intl.DurationFormat(locale, { style: 'long' }).format(duration);
}
const workoutStart = new Date('2025-06-15T07:00:00');
const workoutEnd = new Date('2025-06-15T08:15:00');
formatWorkoutDuration(workoutStart, workoutEnd, 'en');
// "1 hour and 15 minutes"
Obtener partes formateadas para visualización personalizada
El método formatToParts() devuelve un array de objetos que representan cada pieza de la salida formateada. Usa esto para estilizar partes individuales o construir diseños personalizados.
const duration = { hours: 1, minutes: 46, seconds: 40 };
const parts = new Intl.DurationFormat('en', { style: 'long' }).formatToParts(duration);
Cada parte tiene un type y un value. Los tipos incluyen hour, minute, second, literal y etiquetas de unidad como hourUnit, minuteUnit.
[
{ type: "integer", value: "1" },
{ type: "literal", value: " " },
{ type: "unit", value: "hour" },
{ type: "literal", value: ", " },
{ type: "integer", value: "46" },
{ type: "literal", value: " " },
{ type: "unit", value: "minutes" },
{ type: "literal", value: " and " },
{ type: "integer", value: "40" },
{ type: "literal", value: " " },
{ type: "unit", value: "seconds" }
]
Mapea las partes para aplicar estilos personalizados.
function StyledDuration({ duration }) {
const parts = new Intl.DurationFormat('en', { style: 'long' }).formatToParts(duration);
return parts.map((part, i) => {
if (part.type === 'integer') {
return <strong key={i}>{part.value}</strong>;
}
return <span key={i}>{part.value}</span>;
});
}
Reutiliza instancias de formateador para mejorar el rendimiento
Crear un nuevo formateador para cada duración añade sobrecarga. Crea el formateador una vez y reutilízalo.
const formatter = new Intl.DurationFormat('en', { style: 'short' });
const durations = [
{ hours: 1, minutes: 30 },
{ hours: 2, minutes: 15 },
{ hours: 0, minutes: 45 }
];
durations.map(d => formatter.format(d));
// ["1 hr and 30 min", "2 hr and 15 min", "45 min"]
Este patrón mejora el rendimiento al formatear muchas duraciones en bucles o renderizados.
Migra desde la construcción manual de cadenas
Reemplaza la concatenación manual de cadenas con la API. Esto reduce el código y añade localización.
Antes:
function formatDuration(hours, minutes) {
if (hours > 0 && minutes > 0) {
return `${hours}h ${minutes}m`;
} else if (hours > 0) {
return `${hours}h`;
} else {
return `${minutes}m`;
}
}
Después:
function formatDuration(hours, minutes, locale) {
const duration = {};
if (hours > 0) duration.hours = hours;
if (minutes > 0) duration.minutes = minutes;
return new Intl.DurationFormat(locale, { style: 'narrow' }).format(duration);
}
La versión de la API maneja toda la lógica condicional automáticamente y soporta múltiples idiomas.
Migra desde bibliotecas
Bibliotecas como Moment.js y date-fns proporcionan formateo de duraciones pero añaden tamaño al bundle. La API nativa elimina esta dependencia.
Reemplaza el formateo de duraciones de Moment.js:
// Before: Moment.js
const duration = moment.duration(6400, 'seconds');
const formatted = duration.hours() + 'h ' + duration.minutes() + 'm';
// After: Intl.DurationFormat
const duration = {
hours: Math.floor(6400 / 3600),
minutes: Math.floor((6400 % 3600) / 60)
};
new Intl.DurationFormat('en', { style: 'narrow' }).format(duration);
Reemplaza el formateo de duraciones de date-fns:
// Before: date-fns
import { formatDuration, intervalToDuration } from 'date-fns';
const duration = intervalToDuration({ start: 0, end: 6400000 });
const formatted = formatDuration(duration);
// After: Intl.DurationFormat
const ms = 6400000;
const duration = {
hours: Math.floor(ms / 3600000),
minutes: Math.floor((ms % 3600000) / 60000),
seconds: Math.floor((ms % 60000) / 1000)
};
new Intl.DurationFormat('en', { style: 'long' }).format(duration);
La API nativa proporciona la misma funcionalidad sin dependencias.
Soporte de navegadores y polyfills
La API Intl.DurationFormat se convirtió en Baseline en marzo de 2025. Funciona en las últimas versiones de Chrome, Edge, Firefox y Safari.
Verifica el soporte antes de usar:
if (typeof Intl.DurationFormat !== 'undefined') {
const formatter = new Intl.DurationFormat('en', { style: 'short' });
return formatter.format(duration);
} else {
// Fallback for older browsers
return `${duration.hours}h ${duration.minutes}m`;
}
Para un soporte más amplio, usa un polyfill. El proyecto FormatJS proporciona @formatjs/intl-durationformat.
npm install @formatjs/intl-durationformat
Importar y aplicar polyfill si es necesario:
if (!Intl.DurationFormat) {
await import('@formatjs/intl-durationformat/polyfill');
}
El polyfill añade aproximadamente 15 KB comprimidos con gzip. Cárgalo condicionalmente para evitar sobrecarga en navegadores modernos.
Cuándo usar DurationFormat
Usa Intl.DurationFormat al mostrar tiempo transcurrido, tiempo restante o mediciones de duración. Esto incluye reproductores de vídeo, temporizadores, cuentas regresivas, aplicaciones de seguimiento, reservas de viajes y visualizaciones de duración de sesión.
No lo uses para fechas, horas o marcas de tiempo. Usa Intl.DateTimeFormat para esos casos. No lo uses para expresiones de tiempo relativo como "hace 2 horas". Usa Intl.RelativeTimeFormat para esos casos.
La API formatea duraciones, no realiza cálculos de tiempo. Debes calcular tú mismo los valores de duración a partir de fechas, marcas de tiempo u otras fuentes. El formateador solo se encarga de la visualización.