Formateo de Fechas y Números con la API Intl
Has usado Intl.DateTimeFormat e Intl.NumberFormat anteriormente. Pero si tu modelo mental data de hace algunos años, probablemente te estés perdiendo capacidades significativas—particularmente en torno a los controles de redondeo de Intl.NumberFormat y cómo Temporal e Intl trabajan juntos en los runtimes de finales de 2025.
Este artículo proporciona una visión técnica actualizada de la internacionalización de JavaScript a través de la API Intl, enfocándose en lo que ha cambiado y en lo que los desarrolladores experimentados suelen entender incorrectamente.
Puntos Clave
- La API Intl formatea valores en cadenas sensibles a la configuración regional, pero no analiza, calcula ni almacena datos—mantén la presentación separada de la lógica de aplicación.
Intl.NumberFormatahora soporta controles de redondeo avanzados incluyendoroundingMode,roundingIncrementytrailingZeroDisplay.- Los tipos Temporal manejan su propio formateo
toLocaleString()mientras queIntl.DateTimeFormatcontinúa formateando objetosDate. - Siempre reutiliza las instancias de formateadores para mejorar el rendimiento y evita codificar cadenas de salida esperadas en las pruebas.
Qué Hace Realmente Intl
El espacio de nombres Intl maneja el formateo de valores sensible a la configuración regional. No analiza, calcula ni manipula datos—transforma valores en cadenas legibles para humanos según las convenciones culturales.
Dos puntos críticos:
- Intl formatea; no almacena ni computa. La lógica de tu aplicación permanece separada de la presentación.
- La salida varía según el runtime. Los datos de configuración regional subyacentes provienen de las bibliotecas ICU incluidas con los navegadores y Node.js. Las cadenas exactas pueden diferir ligeramente entre Chrome y Safari, o entre versiones de Node.
Nunca codifiques cadenas de salida esperadas en las pruebas. Usa formatToParts() o aserciones estructurales en su lugar.
Intl.DateTimeFormat: Más Allá de las Opciones Básicas
Formateo de Objetos Date
Intl.DateTimeFormat sigue siendo la forma estándar de formatear objetos Date de JavaScript:
const formatter = new Intl.DateTimeFormat('de-DE', {
dateStyle: 'long',
timeStyle: 'short',
timeZone: 'Europe/Berlin'
});
formatter.format(new Date()); // "27. Juni 2025 um 14:30"
Las opciones dateStyle y timeStyle proporcionan configuraciones predefinidas. Cuando necesites control granular, usa opciones individuales como weekday, month, hour y timeZoneName.
Tipos Temporal y Formateo Sensible a la Configuración Regional
Temporal está siendo implementado activamente en los motores modernos de JavaScript, pero aún no cuenta con soporte amplio en todos los navegadores y entornos. Donde está disponible, Temporal.PlainDate, Temporal.ZonedDateTime y otros tipos Temporal se formatean a sí mismos mediante toLocaleString(), en lugar de ser pasados directamente a Intl.DateTimeFormat.prototype.format().
const date = Temporal.PlainDate.from('2025-06-27');
date.toLocaleString('ja-JP', { dateStyle: 'full' });
// "2025年6月27日金曜日"
Intl.DateTimeFormat acepta objetos Date. Los tipos Temporal manejan su propia lógica de formateo y pueden delegar el comportamiento sensible a la configuración regional internamente, pero no son formateados por Intl.DateTimeFormat en sí. Esta distinción importa al diseñar APIs que aceptan entradas de fecha.
Rangos de Fechas con formatRange
Para mostrar rangos de fechas, usa formatRange():
const start = new Date(2025, 5, 27);
const end = new Date(2025, 6, 3);
new Intl.DateTimeFormat('en-US', { dateStyle: 'medium' })
.formatRange(start, end);
// "Jun 27 – Jul 3, 2025"
El formateador colapsa inteligentemente las partes redundantes basándose en las convenciones de la configuración regional.
Discover how at OpenReplay.com.
Controles de Redondeo y Visualización de Intl.NumberFormat
Opciones Modernas de Redondeo
El comportamiento de redondeo de Intl.NumberFormat se ha expandido significativamente en las especificaciones recientes, con soporte variable según el runtime. Más allá de minimumFractionDigits y maximumFractionDigits, ahora tienes:
roundingMode: Controla cómo se redondean los valores (ceil,floor,halfExpand,halfEven, etc.)roundingIncrement: Redondea a incrementos específicos (5, 10, 50, etc.)trailingZeroDisplay: Controla si aparecen ceros finales (autoostripIfInteger)
const formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
roundingMode: 'halfEven',
maximumFractionDigits: 2
});
formatter.format(2.225); // "$2.22" (redondeo bancario)
formatter.format(2.235); // "$2.24"
Patrones de Formateo de Números Sensibles a la Configuración Regional
Para notación compacta y formateo de unidades:
// Notación compacta
new Intl.NumberFormat('en-US', {
notation: 'compact',
compactDisplay: 'short'
}).format(1234567); // "1.2M"
// Formateo de unidades
new Intl.NumberFormat('de-DE', {
style: 'unit',
unit: 'kilometer-per-hour',
unitDisplay: 'short'
}).format(120); // "120 km/h"
Consideraciones Prácticas
Reutiliza las Instancias de Formateadores
Crear formateadores tiene un costo. Almacénalos en caché cuando formatees múltiples valores:
// Haz esto
const priceFormatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
});
prices.map(p => priceFormatter.format(p));
// No esto
prices.map(p => new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}).format(p));
Detección de Características
Verifica las opciones más nuevas programáticamente:
try {
new Intl.NumberFormat('en', { roundingMode: 'halfEven' });
// Característica soportada
} catch (e) {
// Recurre al redondeo predeterminado
}
Configuración Regional vs. Zona Horaria
Estos son conceptos independientes. Una configuración regional (en-GB) determina las convenciones de formateo. Una zona horaria (Europe/London) determina la hora del reloj mostrada. Puedes formatear una fecha con convenciones alemanas mientras muestras la hora de Tokio.
Conclusión
La API Intl para formateo de fechas y formateo de números sensible a la configuración regional ha madurado sustancialmente. La especificación ahora incluye modos de redondeo, controles de visualización y formateo de rangos que eliminan la mayoría de las razones para usar bibliotecas externas.
Los tipos Temporal existen junto a Intl—manejan sus propias llamadas toLocaleString() mientras que Intl.DateTimeFormat continúa formateando objetos Date. Construye tu modelo mental en torno a esta separación, prueba sin expectativas de cadenas codificadas y reutiliza instancias de formateadores para mejorar el rendimiento.
Preguntas Frecuentes
No. Intl.DateTimeFormat.prototype.format() acepta solo objetos Date. Los tipos Temporal como PlainDate y ZonedDateTime tienen sus propios métodos toLocaleString(). No son formateados por Intl.DateTimeFormat en sí, aunque pueden usar datos de configuración regional similares internamente.
Intl depende de los datos de configuración regional ICU incluidos con cada runtime. Chrome, Safari, Firefox y Node.js pueden incluir diferentes versiones de ICU con ligeras variaciones en la salida. Evita codificar cadenas esperadas en las pruebas. Usa formatToParts() o aserciones estructurales para verificar el comportamiento de formateo de manera confiable.
El redondeo bancario (halfEven) redondea los valores de punto medio hacia el dígito par más cercano, reduciendo el sesgo acumulativo de redondeo. Se usa comúnmente en contextos financieros y contables, pero los resultados exactos aún pueden verse afectados por la representación binaria de punto flotante.
Intenta construir un formateador con la opción habilitada. Si el runtime no la soporta, puede lanzar un RangeError o ignorar silenciosamente la opción, dependiendo del motor. Siempre incluye una estrategia de respaldo.
Complete picture for complete understanding
Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.
Check our GitHub repo and join the thousands of developers in our community.