Temporal API

La API Temporal de JavaScript: un reemplazo moderno de Date

JavaScript Date lleva décadas roto de formas bien conocidas. TC39 Temporal — Stage 4 desde principios de 2025, ya en navegadores modernos y Node.js — separa con limpieza los instantes, las fechas de reloj de pared y las fechas-hora zonificadas. Esta guía explica los nuevos tipos, cómo se corresponden con los timestamps Unix y cómo migrar.

Temporal vs Date de un vistazo

El Date integrado de JavaScript ha sido una fuente conocida de bugs durante décadas: es mutable, solo entiende la zona local y UTC, sus meses se indexan desde cero y su parsing está laxamente especificado. Temporal es el reemplazo normalizado — Stage 4 y parte de ECMAScript 2026 — y corrige cada uno de esos problemas con tipos inmutables hechos a propósito. La tabla siguiente es el contraste general; el resto de esta guía cubre los tipos y cómo se corresponden con los timestamps Unix.

AspectoDate (heredado)Temporal
MutabilidadMutableInmutable
PrecisiónMilisegundosNanosegundos
Zonas horariasSolo local + UTCCualquier zona IANA (ZonedDateTime)
Indexación de mesesBase 0 (0 = enero)Base 1 (1 = enero)
ParsingPermisivo, definido por la implementaciónISO 8601 / RFC 9557 estricto
Instante vs reloj de paredConfundidos en un solo tipoTipos separados

Por qué existe Temporal

JavaScript Date confunde varios conceptos distintos: un instante exacto, una hora de reloj de pared y una fecha-hora zonificada. Date también tiene rarezas de parsing bien conocidas, una sola zona (la del usuario) y precisión de milisegundos. Temporal expone los conceptos subyacentes como tipos separados y admite precisión de nanosegundos, zonas IANA arbitrarias y sistemas de calendario explícitos.

  • Stage 4 desde principios de 2025; lanzado primero por defecto en Firefox 139
  • Ahora disponible en Chrome 144+, Firefox 139+ y Node.js 26+
  • Los polyfills (@js-temporal/polyfill) funcionan en cualquier entorno moderno
  • Diseñado para coexistir con Date — existen métodos de interoperabilidad en ambos sentidos

Los tipos esenciales de Temporal

Un pequeño conjunto de tipos cubre con limpieza el problema de las fechas-hora. Cada uno tiene una forma de cadena canónica (ISO 8601, extendida por RFC 9557 para el tipo zonificado):

TipoRepresentaCadena de ejemplo
Temporal.InstantUn instante exacto, como un timestamp Unix (precisión ns)2026-01-01T00:00:00Z
Temporal.ZonedDateTimeInstante + zona IANA + calendario2026-01-01T09:00:00+09:00[Asia/Tokyo]
Temporal.PlainDateTimeFecha + hora, sin zona2026-01-01T09:00:00
Temporal.PlainDateUna fecha de calendario (p. ej. un cumpleaños)2026-01-01
Temporal.PlainTimeUna hora de reloj de pared09:00:00
Temporal.DurationUna duración, consciente de unidadesP3DT4H10M

Trabajar con timestamps Unix

Temporal.Instant es el tipo timestamp Unix. La API publicada solo expone conversiones epoch en milisegundos y nanosegundos — los métodos anteriores fromEpochSeconds y fromEpochMicroseconds se eliminaron antes del Stage 4 — así que convierte segundos Unix multiplicando por 1000. Usa Instant para almacenamiento y transporte, y ZonedDateTime cuando necesites una vista de reloj de pared en una zona concreta.

  • Temporal.Now.instant() — el momento exacto actual
  • Temporal.Instant.fromEpochMilliseconds(Date.now()) — desde un timestamp JS en milisegundos
  • Temporal.Instant.fromEpochMilliseconds(1700000000 * 1000) — desde segundos Unix (× 1000)
  • Temporal.Instant.fromEpochNanoseconds(1700000000000000000n) — desde nanosegundos (BigInt)
  • instant.epochMilliseconds y instant.epochNanoseconds — leer de vuelta el valor epoch
  • instant.toZonedDateTimeISO("America/New_York") — una vista de reloj de pared en una zona

Zonas y DST manejados correctamente

ZonedDateTime lleva una zona IANA, así que las transiciones de DST, las horas de hueco y las horas de solapamiento se manejan todas explícitamente. La opción de desambiguación te deja elegir una política para horas locales ambiguas, y el formato de cadena canónico es RFC 9557 (un timestamp ISO 8601 con la zona entre corchetes).

  • zdt.timeZoneId — el nombre IANA (p. ej. America/Los_Angeles)
  • zdt.add({ hours: 1 }) — aritmética consciente del DST en términos de reloj de pared
  • zdt.until(zdt2) — distancia entre dos fechas-hora zonificadas
  • Opciones de desambiguación: "earlier", "later", "compatible" (por defecto — posterior para el hueco, anterior para el solapamiento), "reject"
  • Ida y vuelta: instante ↔ fecha-hora zonificada es sin pérdida

Patrones de migración desde Date

La estrategia de migración más sencilla es introducir Temporal primero en las fronteras (parsing de entrada, formateo de salida) e ir moviendo gradualmente la lógica interna.

  • Date → Instant: Temporal.Instant.fromEpochMilliseconds(date.getTime())
  • Instant → Date: new Date(instant.epochMilliseconds)
  • Para código nuevo, prefiere Temporal en todas partes y convierte a Date solo en los bordes de la API
  • date-fns y Luxon tienen ambos modos / adaptadores conscientes de Temporal
  • JSON: Temporal.Instant.prototype.toJSON devuelve una cadena ISO 8601

Soporte en navegadores y runtimes

Temporal se lanzó en 2025 y el soporte nativo ya es amplio, pero aún no universal. El polyfill es la vía más segura mientras los navegadores antiguos y Safari estable sigan en servicio.

  • Firefox 139+: el primero en lanzarlo, habilitado por defecto (mayo de 2025)
  • Chrome 144+: habilitado por defecto (enero de 2026)
  • Node.js 26+: habilitado por defecto (mayo de 2026)
  • Safari: disponible en Technology Preview, aún no en una versión estable
  • Polyfill: @js-temporal/polyfill o temporal-polyfill — misma API, cualquier entorno moderno

Referencias relacionadas

FAQ

¿Es Temporal un reemplazo de Date?
Sí — Temporal está diseñado para reemplazar por completo a Date en el código nuevo. Date permanece en el lenguaje por compatibilidad hacia atrás, y ambos interoperan vía milisegundos epoch.
¿Cómo convierto un timestamp Unix a Temporal?
Usa Temporal.Instant.fromEpochMilliseconds(). Para segundos Unix, multiplica por 1000: Temporal.Instant.fromEpochMilliseconds(seconds * 1000). La API publicada solo tiene fromEpochMilliseconds y fromEpochNanoseconds — el antiguo método fromEpochSeconds se eliminó antes de que Temporal alcanzara el Stage 4.
¿Temporal admite nanosegundos?
Sí. Temporal.Instant tiene precisión de nanosegundos internamente y expone epochNanoseconds como un BigInt.
¿Puedo usar Temporal en Node.js hoy?
En Node.js 26+ Temporal está habilitado por defecto. En versiones anteriores de Node, instala @js-temporal/polyfill — la superficie de la API es idéntica.
¿Qué navegadores admiten Temporal?
Firefox 139+ (mayo de 2025), Chrome 144+ (enero de 2026) y Node.js 26+ (mayo de 2026) incluyen Temporal por defecto. Safari lo tiene en Technology Preview. Para cualquier cosa anterior, usa el @js-temporal/polyfill.
¿Cómo maneja Temporal el hueco del DST?
Los constructores y la aritmética de ZonedDateTime aceptan una opción de desambiguación. "compatible" (por defecto) elige el instante posterior para los huecos y el anterior para los solapamientos; "reject" lanza un error si la hora local es ambigua.