Cómo obtener partes individuales de una fecha formateada en JavaScript
Usa formatToParts() para acceder a cada componente de una fecha formateada según la configuración regional por separado
Introducción
El método format() devuelve una cadena formateada completa como "15 de enero de 2025" o "15/01/2025". Esto funciona bien para una visualización simple, pero no puedes aplicar estilos diferentes a partes individuales. No puedes poner el nombre del mes en negrita, colorear el año de forma diferente o aplicar marcado personalizado a componentes específicos.
JavaScript proporciona el método formatToParts() para resolver este problema. En lugar de devolver una única cadena, devuelve un array de objetos, cada uno representando una parte de la fecha formateada. Cada parte tiene un tipo como month, day o year, y un valor como January, 15 o 2025. Luego puedes procesar estas partes para aplicar estilos personalizados, construir diseños complejos o integrar fechas formateadas en interfaces de usuario enriquecidas.
Por qué las cadenas formateadas son difíciles de personalizar
Cuando recibes una cadena formateada como "15 de enero de 2025", no puedes identificar fácilmente dónde termina el mes y dónde comienza el día. Diferentes configuraciones regionales colocan los componentes en diferentes órdenes. Algunas configuraciones regionales usan diferentes separadores. Analizar estas cadenas de forma fiable requiere una lógica compleja que duplica las reglas de formato ya implementadas en la API Intl.
Considera una aplicación de calendario que muestra fechas con el nombre del mes en negrita. Con format(), necesitarías:
- Detectar qué caracteres representan el nombre del mes
- Tener en cuenta espacios y puntuación entre componentes
- Manejar diferentes formatos de mes en distintas configuraciones regionales
- Analizar la cadena cuidadosamente para evitar romper la fecha
Este enfoque es frágil y propenso a errores. Cualquier cambio en las reglas de formato de la configuración regional rompe tu lógica de análisis.
El método formatToParts() elimina este problema al proporcionar los componentes por separado. Recibes datos estructurados que te indican exactamente qué parte es cuál, independientemente de la configuración regional.
Usar formatToParts para obtener componentes de fecha
El método formatToParts() funciona de forma idéntica a format() excepto por su valor de retorno. Creas un formateador con las mismas opciones y luego llamas a formatToParts() en lugar de format().
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
const date = new Date(2025, 0, 15);
const parts = formatter.formatToParts(date);
console.log(parts);
Esto genera un array de objetos:
[
{ type: "month", value: "January" },
{ type: "literal", value: " " },
{ type: "day", value: "15" },
{ type: "literal", value: ", " },
{ type: "year", value: "2025" }
]
Cada objeto contiene una propiedad type que identifica lo que representa la parte y una propiedad value que contiene la cadena real. Las partes aparecen en el mismo orden en que aparecerían en la salida formateada.
Puedes verificar esto uniendo todos los valores:
const formatted = parts.map(part => part.value).join("");
console.log(formatted);
// Output: "January 15, 2025"
Las partes concatenadas producen exactamente la misma salida que llamar a format().
Comprender los tipos de partes
La propiedad type identifica cada componente. Diferentes opciones de formato producen diferentes tipos de partes.
Para formato de fecha básico:
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
const date = new Date(2025, 0, 15);
const parts = formatter.formatToParts(date);
console.log(parts);
// [
// { type: "month", value: "January" },
// { type: "literal", value: " " },
// { type: "day", value: "15" },
// { type: "literal", value: ", " },
// { type: "year", value: "2025" }
// ]
El tipo month representa el nombre o número del mes. El tipo day representa el día del mes. El tipo year representa el año. El tipo literal representa espacios, puntuación u otro texto insertado por el formateador.
Para fechas con días de la semana:
const formatter = new Intl.DateTimeFormat("en-US", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric"
});
const date = new Date(2025, 0, 15);
const parts = formatter.formatToParts(date);
console.log(parts);
// [
// { type: "weekday", value: "Wednesday" },
// { type: "literal", value: ", " },
// { type: "month", value: "January" },
// { type: "literal", value: " " },
// { type: "day", value: "15" },
// { type: "literal", value: ", " },
// { type: "year", value: "2025" }
// ]
El tipo weekday representa el día de la semana.
Para fechas con horas:
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric",
hour: "numeric",
minute: "numeric",
second: "numeric"
});
const date = new Date(2025, 0, 15, 14, 30, 45);
const parts = formatter.formatToParts(date);
console.log(parts);
// [
// { type: "month", value: "January" },
// { type: "literal", value: " " },
// { type: "day", value: "15" },
// { type: "literal", value: ", " },
// { type: "year", value: "2025" },
// { type: "literal", value: " at " },
// { type: "hour", value: "2" },
// { type: "literal", value: ":" },
// { type: "minute", value: "30" },
// { type: "literal", value: ":" },
// { type: "second", value: "45" },
// { type: "literal", value: " " },
// { type: "dayPeriod", value: "PM" }
// ]
Los tipos hour, minute y second representan componentes de tiempo. El tipo dayPeriod representa AM o PM en formato de 12 horas.
Aplicar estilos personalizados a partes de fecha
El caso de uso principal para formatToParts() es aplicar diferentes estilos a diferentes componentes. Puedes procesar el array de partes para envolver tipos específicos en elementos HTML.
Poner el nombre del mes en negrita:
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
const date = new Date(2025, 0, 15);
const parts = formatter.formatToParts(date);
const html = parts
.map(part => {
if (part.type === "month") {
return `<strong>${part.value}</strong>`;
}
return part.value;
})
.join("");
console.log(html);
// Output: "<strong>January</strong> 15, 2025"
Este enfoque funciona para cualquier lenguaje de marcado. Puedes generar HTML, JSX o cualquier otro formato procesando el array de partes.
Aplicar un estilo diferente al año:
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
const date = new Date(2025, 0, 15);
const parts = formatter.formatToParts(date);
const html = parts
.map(part => {
if (part.type === "year") {
return `<span class="text-gray-500">${part.value}</span>`;
}
return part.value;
})
.join("");
console.log(html);
// Output: "January 15, <span class="text-gray-500">2025</span>"
Este patrón es común en visualizaciones de calendario donde diferentes componentes necesitan diferente énfasis visual.
Crear visualizaciones de fecha personalizadas con múltiples estilos
Las interfaces complejas a menudo combinan múltiples reglas de estilo. Puedes aplicar diferentes clases o elementos a diferentes tipos de partes simultáneamente.
const formatter = new Intl.DateTimeFormat("en-US", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric"
});
const date = new Date(2025, 0, 15);
const parts = formatter.formatToParts(date);
const html = parts
.map(part => {
switch (part.type) {
case "weekday":
return `<span class="weekday">${part.value}</span>`;
case "month":
return `<span class="month">${part.value}</span>`;
case "day":
return `<span class="day">${part.value}</span>`;
case "year":
return `<span class="year">${part.value}</span>`;
case "literal":
return `<span class="literal">${part.value}</span>`;
default:
return part.value;
}
})
.join("");
console.log(html);
// Output: "<span class="weekday">Wednesday</span><span class="literal">, </span><span class="month">January</span><span class="literal"> </span><span class="day">15</span><span class="literal">, </span><span class="year">2025</span>"
Este control granular permite un estilo preciso para cada componente. Luego puedes usar CSS para aplicar estilos diferentes a cada clase.
Crear diseños de fecha personalizados
Puedes reorganizar los componentes de fecha en diseños personalizados que difieren del formato estándar de la configuración regional. Extrae partes específicas y compónlas en cualquier orden.
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
const date = new Date(2025, 0, 15);
const parts = formatter.formatToParts(date);
const day = parts.find(p => p.type === "day").value;
const month = parts.find(p => p.type === "month").value;
const year = parts.find(p => p.type === "year").value;
const customLayout = `
<div class="date-card">
<div class="day-large">${day}</div>
<div class="month-small">${month}</div>
<div class="year-small">${year}</div>
</div>
`;
console.log(customLayout);
Esto crea un diseño de tarjeta vertical con el día mostrado de forma prominente, seguido del mes y el año. Los componentes permanecen correctamente localizados aunque el diseño difiera del formato estándar.
Todos los tipos de partes disponibles
La propiedad type puede tener estos valores dependiendo de las opciones de formato utilizadas:
weekday: día de la semana como lunes o lunera: indicador de era como a. C., d. C. o a. e. c.year: año como 2025month: nombre o número del mes como enero o 01day: día del mes como 15dayPeriod: a. m. o p. m. u otros períodos del día específicos de la configuración regionalhour: hora como 14 o 2minute: minuto como 30second: segundo como 45fractionalSecond: milisegundos u otras fracciones de segundotimeZoneName: nombre de zona horaria como PST o hora estándar del Pacíficoliteral: espaciado, puntuación u otro texto añadido por el formatorelatedYear: año gregoriano en sistemas de calendario alternativosyearName: año con nombre en algunos sistemas de calendariounknown: tokens no reconocidos
No todas las opciones de formato producen todos los tipos de partes. Las partes que recibes dependen del valor de la fecha y la configuración del formateador.
Fechas con indicadores de era:
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
era: "short"
});
const date = new Date(-100, 0, 1);
const parts = formatter.formatToParts(date);
console.log(parts);
// [
// { type: "year", value: "101" },
// { type: "literal", value: " " },
// { type: "era", value: "BC" }
// ]
Fechas con zonas horarias:
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric",
hour: "numeric",
minute: "numeric",
timeZoneName: "short"
});
const date = new Date(2025, 0, 15, 14, 30);
const parts = formatter.formatToParts(date);
console.log(parts);
// Parts will include { type: "timeZoneName", value: "PST" } or similar
Fechas con segundos fraccionarios:
const formatter = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
minute: "numeric",
second: "numeric",
fractionalSecondDigits: 3
});
const date = new Date(2025, 0, 15, 14, 30, 45, 123);
const parts = formatter.formatToParts(date);
// Parts will include { type: "fractionalSecond", value: "123" }
Resaltar componentes de fecha condicionalmente
Algunas aplicaciones resaltan componentes de fecha específicos según la lógica de negocio. Con formatToParts(), puedes aplicar estilos según el valor de la fecha mientras mantienes el formato adecuado.
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
function formatDateWithHighlight(date) {
const parts = formatter.formatToParts(date);
const isWeekend = date.getDay() === 0 || date.getDay() === 6;
const html = parts
.map(part => {
if (part.type === "day" && isWeekend) {
return `<span class="text-blue-600 font-bold">${part.value}</span>`;
}
return part.value;
})
.join("");
return html;
}
const saturday = new Date(2025, 0, 18);
console.log(formatDateWithHighlight(saturday));
// Output: "January <span class="text-blue-600 font-bold">18</span>, 2025"
const monday = new Date(2025, 0, 13);
console.log(formatDateWithHighlight(monday));
// Output: "January 13, 2025"
La fecha recibe el formato adecuado para la configuración regional mientras se aplica el estilo condicional según la lógica de negocio.
Crear visualizaciones de fecha accesibles
Puedes usar formatToParts() para añadir atributos de accesibilidad a las fechas formateadas. Esto ayuda a los lectores de pantalla a anunciar los valores correctamente.
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
function formatAccessibleDate(date) {
const parts = formatter.formatToParts(date);
const formatted = parts.map(part => part.value).join("");
const isoDate = date.toISOString().split('T')[0];
return `<time datetime="${isoDate}">${formatted}</time>`;
}
const date = new Date(2025, 0, 15);
console.log(formatAccessibleDate(date));
// Output: "<time datetime="2025-01-15">January 15, 2025</time>"
Esto garantiza que los lectores de pantalla puedan anunciar la fecha correctamente mientras la visualización muestra la versión formateada según la configuración regional.
Cómo las partes preservan el formato específico de la configuración regional
El array de partes mantiene las reglas de formato específicas de la configuración regional automáticamente. Diferentes configuraciones regionales colocan los componentes en diferentes órdenes y usan diferentes formatos, pero formatToParts() maneja estas diferencias.
const usFormatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
const date = new Date(2025, 0, 15);
console.log(usFormatter.formatToParts(date));
// [
// { type: "month", value: "January" },
// { type: "literal", value: " " },
// { type: "day", value: "15" },
// { type: "literal", value: ", " },
// { type: "year", value: "2025" }
// ]
const ukFormatter = new Intl.DateTimeFormat("en-GB", {
year: "numeric",
month: "long",
day: "numeric"
});
console.log(ukFormatter.formatToParts(date));
// [
// { type: "day", value: "15" },
// { type: "literal", value: " " },
// { type: "month", value: "January" },
// { type: "literal", value: " " },
// { type: "year", value: "2025" }
// ]
El formato británico coloca el día antes del mes. Tu código de estilo procesa el array de partes de la misma manera independientemente de la configuración regional, y el formato se adapta automáticamente.
const jpFormatter = new Intl.DateTimeFormat("ja-JP", {
year: "numeric",
month: "long",
day: "numeric"
});
console.log(jpFormatter.formatToParts(date));
// [
// { type: "year", value: "2025" },
// { type: "literal", value: "年" },
// { type: "month", value: "1月" },
// { type: "day", value: "15" },
// { type: "literal", value: "日" }
// ]
El formato japonés usa un orden diferente e incluye literales de caracteres como 年 (año) y 日 (día). El array de partes refleja estas convenciones específicas de la configuración regional automáticamente.
Combinar formatToParts con componentes de framework
Los frameworks modernos como React pueden usar formatToParts() para construir componentes de manera eficiente.
function DateDisplay({ date, locale, options }) {
const formatter = new Intl.DateTimeFormat(locale, options);
const parts = formatter.formatToParts(date);
return (
<span className="date-display">
{parts.map((part, index) => {
if (part.type === "month") {
return <strong key={index}>{part.value}</strong>;
}
if (part.type === "year") {
return <span key={index} className="text-sm text-gray-500">{part.value}</span>;
}
return <span key={index}>{part.value}</span>;
})}
</span>
);
}
Este componente aplica diferentes estilos a diferentes partes mientras mantiene el formato adecuado para cualquier configuración regional.
Cuándo usar formatToParts versus format
Usa format() cuando necesites una cadena formateada simple sin ninguna personalización. Este es el caso común para la mayoría de visualizaciones de fechas.
Usa formatToParts() cuando necesites:
- Aplicar diferentes estilos a diferentes partes de la fecha
- Construir HTML o JSX con fechas formateadas
- Añadir atributos o metadatos a componentes específicos
- Reorganizar componentes de fecha en diseños personalizados
- Integrar fechas formateadas en diseños complejos
- Procesar la salida formateada de forma programática
El método formatToParts() tiene una sobrecarga ligeramente mayor que format() porque crea un array de objetos en lugar de una única cadena. Esta diferencia es insignificante para aplicaciones típicas, pero si formateas miles de fechas por segundo, format() tiene mejor rendimiento.
Para la mayoría de aplicaciones, elige según tus necesidades de estilo en lugar de preocupaciones de rendimiento. Si no necesitas personalizar la salida, usa format(). Si necesitas estilos o marcado personalizados, usa formatToParts().