Escribir una fecha en ISO 8601 y por qué es el único formato sin ambigüedad
Publicado el 13/8/2026 · 17 min de lectura · Herramientas de texto e idioma
Daniel Okonkwo — Desarrollador front-end y redactor de Tecnología en OneKitly
Rendimiento web · Formatos de archivo
Verificado con 4 fuentes
Escribe primero el año, luego el mes y luego el día, cada uno con ceros a la izquierda: 2026-02-01. El orden es todo el truco. Como los campos van de la unidad mayor a la menor y cada uno tiene un ancho fijo, comparar dos cadenas carácter a carácter da la misma respuesta que comparar los dos instantes, y por eso ordenar una carpeta de archivos nombrados así los deja en orden cronológico sin ninguna lógica de fechas. La hora se une a la fecha con una T mayúscula y se añade un desfase respecto a UTC: 2026-02-01T09:30:00+01:00, o Z cuando el desfase es cero. Una fecha-hora sin desfase es una fecha local cuyo significado depende de dónde se lea, justo la ambigüedad que el formato existe para eliminar, así que añade el desfase salvo que de verdad quieras hablar de un reloj de pared. La herramienta se probó con esto: guarda un instante como siete enteros y convierte con aritmética entera en vez de con un objeto Date, de modo que 2026-08-13T00:30:00+02:00 vuelve como 2026-08-12T22:30:00Z, un día antes y correcto, con una marca Unix de 1786573800 idéntica a Date.UTC. Su botón «Ahora» lee el reloj en UTC, así que justo después de medianoche en París rellena la fecha del día anterior: sorprendente, no erróneo. Dos avisos. El orden textual solo equivale al orden temporal si todas las cadenas llevan el mismo desfase; mezcla Z y +02:00 y el orden queda mal en silencio. Y la ISO 8601 es más amplia que la RFC 3339, que es lo que de verdad exigen la mayoría de las API: una fecha sola, una fecha de semana, una cadena en formato básico y una hora 24 son ISO 8601 válida, y ninguna es RFC 3339 válida.
01/02/2026 es el 1 de febrero en casi toda Europa y el 2 de enero en Estados Unidos, y nada en la cadena dice cuál. ISO 8601 lo resuelve, se ordena como texto, y deja de valer en cuatro puntos concretos que la RFC 3339 rechaza.
01/02/2026 y los seis idiomas en los que está escrito este sitio
Un lector en París, Madrid, Lisboa, Berlín o Roma lee 01/02/2026 como el 1 de febrero. Un lector en Estados Unidos lee las mismas ocho cifras como el 2 de enero. Nada en la cadena decide entre ambos: las dos lecturas son completas, las dos son convencionales, y las dos se equivocan aproximadamente la mitad de las veces en cuanto la cadena ha viajado.
El fallo es silencioso, y eso es lo que lo hace caro. Un formulario acepta la fecha, una base la guarda, un informe la imprime, y nada protesta hasta el día doce del mes, cuando las dos lecturas dejan de producir cada una una fecha válida y una acaba lanzando un error. Todo lo que estaba entre el 1 y el 12 se desplazó en silencio. Una entrega prevista para el 3 de abril llega el 4 de marzo, una factura queda fechada once meses antes, y la traza de auditoría registra ambas como asientos perfectamente normales.
2026-02-01 no tiene segunda lectura. El año va primero porque es la unidad mayor, el mes después, el día al final, y cada uno se rellena a un ancho fijo. No hay locale que consultar, ni convención de separador que adivinar, ni mes que pueda confundirse con un día. Esa es toda la aportación de la norma, y basta.
Ordenar como texto y ordenar en el tiempo son la misma operación
Ordena los campos de mayor a menor, rellena cada uno a un ancho fijo, y la comparación lexicográfica se convierte gratis en comparación cronológica. Se pasaron cinco instantes por la herramienta, ordenados una vez como cadenas y otra por sus marcas Unix: los dos órdenes fueron idénticos. Esa propiedad es la razón de que una carpeta de archivos llamados 2026-02-01-notas.md, 2026-02-11-notas.md y 2026-10-02-notas.md quede en el orden correcto en cualquier gestor de archivos, cualquier shell y cualquier listado de copias de seguridad, sin ningún análisis de fechas en toda la cadena.
La propiedad tiene una condición fácil de perder: todas las cadenas deben llevar el mismo desfase. Se pasaron dos instantes para mostrarlo. 2026-01-05T09:00:00Z y 2026-01-05T10:00:00+02:00 se ordenan en ese orden como texto, porque el carácter 9 precede al carácter 1 seguido de 0. Sus marcas Unix son 1767603600 y 1767600000, así que el segundo ocurrió primero. El orden textual es erróneo y nada lo avisa. Si una columna puede contener desfases mezclados, normalízalo todo a Z antes de ordenar, u ordena por la marca de tiempo.
El mismo razonamiento explica la convención de nombres de archivo. Pon la fecha al principio del nombre y la carpeta se ordena sola; ponla al final y se ordena por lo que la precede. Usa guiones y no barras, porque la barra es separador de rutas en todos los sistemas, y los dos puntos —legales en una hora pero prohibidos en un nombre de archivo en Windows— explican por qué un nombre con marca de tiempo suele caer en 2026-02-01T093000Z, el formato básico que la norma también define.
La T, la Z y un desfase que no es una zona horaria
La T mayúscula une la fecha con la hora. Está ahí porque una fecha y una hora son dos representaciones distintas y algo tiene que decir dónde acaba una y empieza la otra; un espacio bastaría para una persona, y es justo lo que imprime una base de datos, pero la norma estricta quiere la T. La Z final significa desfase cero —Zulu, del alfabeto fonético militar— y es intercambiable con +00:00.
Un desfase como +02:00 dice cuánto se aparta el reloj de pared de UTC en ese instante, y nada más. No nombra a París: también es El Cairo, Johannesburgo, Helsinki y media Europa en el mismo momento, y ese mismo reloj parisino está en +01:00 en enero. Por eso una cita futura debe guardarse como identificador de zona —Europe/Paris— con la hora local, y no como un desfase. Guarda 2027-03-28T10:00:00+01:00 para una reunión y será a las nueve de la mañana después del cambio de hora, cosa que nadie acordó.
Una fecha-hora sin desfase alguno es una fecha local, y su significado es el que decida la máquina del lector. Es ISO 8601 válida y a veces es lo que quieres —una tienda abre a las 09:00 en la ciudad donde está—, pero no es un instante, y tratarla como tal es la manera en que una línea de registro venida de un servidor extranjero llega a la hora equivocada, y en que una fecha de nacimiento en una base se convierte en el día anterior para quien esté al oeste del meridiano.
A la caza del desfase de un día en torno a medianoche, sin encontrarlo
El defecto más común en la herramienta de fechas es una conversión que pasa por la zona horaria local del navegador y cae un día de más cerca de medianoche. Esta no lo tiene, por una razón estructural: nunca toca la hora local. Un instante se guarda como siete enteros —año, mes, día, hora, minuto, segundo y desfase en minutos— y la conversión a UTC desplaza el número de día con aritmética entera en vez de construir un Date. El botón «Ahora» lee el reloj con getUTCFullYear y sus hermanas y fija el desfase en UTC+00:00.
Los casos límite se probaron a propósito. París a las 00:30 del 13 de agosto con desfase +02:00 da una forma UTC 2026-08-12T22:30:00Z y una fecha HTTP Wed, 12 Aug 2026 22:30:00 GMT: un día antes, lo cual es correcto, porque es el mismo instante. Nueva York a las 23:30 del 12 de agosto con desfase −04:00 va en sentido contrario, hasta 2026-08-13T03:30:00Z. Las islas Chatham a las 00:10 del 1 de enero con desfase +12:45 salen como 2025-12-31T11:25:00Z, cruzando a la vez un día y un año. Cinco de estos casos se contrastaron con Date.UTC, incluido el 1969-07-20T20:17:40Z anterior a la época, cuya marca de −14 182 940 coincidió exactamente.
Lo único que parece un desfase de un día es el botón «Ahora», y es una decisión deliberada que se transparenta. Como el reloj se lee en UTC, un lector parisino que lo pulse a las doce y media de la noche del 13 de agosto ve el campo de fecha rellenado con el 12 de agosto y la hora con 22:30. Es el mismo momento expresado en la zona por defecto de la herramienta, no la fecha de ayer. Si quieres tu propio reloj de pared, escribe la fecha y la hora a mano y elige tu desfase en la lista.
La RFC 3339 es lo que quiere decir tu API, y es más estrecha
Cuando una API dice que quiere ISO 8601, casi siempre quiere RFC 3339, que se describe a sí misma como un perfil de ISO 8601 para uso en Internet. Un perfil es un subconjunto: todo lo que la RFC 3339 acepta es ISO 8601, y buena parte de la ISO 8601 no es RFC 3339. Su gramática exige una fecha completa, después una T, después una hora completa y después un desfase; no se puede omitir nada.
Cuatro diferencias importan en la práctica, todas legibles en la propia gramática de la RFC. Su hora se define como dos cifras entre 00 y 23, así que 24:00 —fin de día legal en ISO, que nombra el mismo instante que la medianoche del día siguiente— no es RFC 3339. Su desfase se escribe signo, dos cifras, dos puntos y dos cifras más: +0200 y +02 son ISO 8601 y ninguno es RFC 3339. No tiene fechas de semana ni fechas ordinales, así que 2026-W33-4 y 2026-225 quedan fuera. Y una fecha desnuda como 2026-08-13, o un año y un mes, o un año solo, no es en absoluto una fecha-hora según la RFC 3339.
Dos sutilezas van en sentido contrario, allí donde la RFC 3339 es más permisiva. Da a −00:00 un significado propio: se conoce la hora UTC pero no el desfase local, cosa deliberadamente distinta de Z o de +00:00. Y una nota de la misma sección dice que las aplicaciones pueden usar un espacio en lugar de la T por legibilidad, que es justo lo que imprimen las bases de datos. La herramienta acepta un espacio pegado y te avisa de que lo ha visto; también acepta −00:00 y lo convierte en silencio en Z, de modo que la distinción que traza la RFC no sobrevive a un viaje de ida y vuelta.
Una consecuencia merece señalarse, porque la herramienta no lo hace. Su campo de salida principal, el etiquetado como forma extendida de fecha y hora, es RFC 3339 siempre que la hora esté entre 00 y 23, y no lo es cuando la hora vale 24, cosa que el analizador acepta. Pega 2026-08-13T24:00:00Z y ese campo te lo devuelve tal cual, y el campo etiquetado como fecha de correo imprime una hora que la RFC 5322 tampoco permite. La línea UTC de al lado sí es correcta: indica 2026-08-14T00:00:00Z. Si copias un valor hacia una API, copia ese.
Fechas de semana, fechas ordinales y las pequeñas cosas que la herramienta falla
La ISO 8601 define dos formas más de fecha y la herramienta imprime ambas. Una fecha de semana nombra el año, la semana y el día de la semana, y su año no siempre es el año civil: una semana pertenece al año que contiene su jueves. Pasa el 1 de enero de 2027 por la herramienta y vuelve como 2026-W53-5; pasa el 31 de diciembre de 2024 y vuelve como 2025-W01-2. Ambos se comprobaron. Una fecha ordinal nombra el año y el día dentro de él, así que el 13 de agosto de 2026 es 2026-225. Las dos se ordenan lexicográficamente igual de bien que las fechas civiles, pero no mezcles nunca las tres formas en una misma columna, porque 2026-W33-4 y 2026-08-13 se ordenan entre sí como cadenas, sin ninguna relación con el tiempo.
Tres pequeños defectos aparecieron en las pruebas y conviene conocerlos más que temerlos. Un segundo de 60 se acepta en cualquier sitio —pega 2026-08-13T00:30:60Z y la herramienta lo toma y calcula una marca Unix de 1786581060, que son las 00:31:00—, mientras que tanto la norma como la RFC solo admiten 60 bajo las reglas del segundo intercalar. Las fracciones de segundo se leen y luego se tiran: 2026-08-13T00:30:00.123Z vuelve como 2026-08-13T00:30:00Z, sin aviso alguno de que los milisegundos han desaparecido. Y el analizador de duraciones rechaza P0D, una duración cero perfectamente legal, porque descarta toda duración cuyos campos valgan todos cero.
Lo que hace bien merece la misma frase. Rechaza 2026-02-30 y 2026-08-13T25:00:00Z, rechaza un 2026-8-3 sin rellenar, y rechaza sin más 13/08/2026 y 08/13/2026, que es la respuesta correcta para una herramienta cuyo trabajo es decir qué es y qué no es ISO 8601. Lee el formato básico 20260813T003000+0200, lee una t y una z minúsculas, y te dice cuál de las tres formas de fecha ha reconocido. Las duraciones también se analizan bien, incluida la coma decimal de P1,5D, que normaliza a P1.5D.
| Cadena | Estado | Por qué |
|---|---|---|
| 2026-08-13T00:30:00+02:00 | Ambas | Fecha completa, T, hora completa, desfase con dos puntos: exactamente la gramática RFC 3339 |
| 2026-08-13 | Solo ISO 8601 | La RFC 3339 define una fecha-hora, no una fecha sola |
| 2026-W33-4T12:00:00+02:00 | Solo ISO 8601 | Las fechas de semana no están en la gramática RFC 3339; la herramienta la lee como 13 de agosto de 2026 |
| 20260813T003000+0200 | Solo ISO 8601 | El formato básico quita los separadores; la RFC 3339 los exige |
| 2026-08-13T24:00:00Z | Solo ISO 8601 — y la herramienta lo reimprime | La RFC 3339 fija la hora entre 00 y 23; la línea UTC muestra correctamente 2026-08-14T00:00:00Z |
| 2026-08-13 00:30:00Z, con un espacio | RFC 3339 por una nota; la herramienta lo acepta y lo indica | Una nota de la sección 5.6 permite un espacio por legibilidad; la norma estricta quiere la T |
| 2026-08-13T00:30:00-00:00 | Solo RFC 3339; la herramienta lo convierte en Z | La sección 4.3 le da el sentido «desfase desconocido», que la conversión borra |
| 2026-08-13T00:30:60Z | Ninguna, y la herramienta lo acepta | Un segundo de 60 es un segundo intercalar, solo a las 23:59:60; la marca sale como 00:31:00 |
| 13/08/2026 y 08/13/2026 | Ninguna; la herramienta rechaza ambas | La ambigüedad que toda la norma existe para eliminar: rechazar es la respuesta correcta |
Preguntas frecuentes
- ¿Debo escribir el desfase o usar Z en todas partes?
- Para todo lo que guardes, registres o envíes entre máquinas, normaliza a Z. Cada valor lleva entonces el mismo desfase, así que el orden textual equivale al temporal, las comparaciones no necesitan conversión y no hay nada que fallar. Conserva el desfase local solo cuando la lectura local sea en sí misma el hecho: un recibo que deba decir que la transacción ocurrió a las 09:15 en la mañana de la tienda, una salida de tren impresa para los pasajeros. Y para una cita futura, ninguno de los dos sirve: guarda el identificador de zona y la hora local, porque el desfase que esa zona tendrá en esa fecha es una decisión que nadie ha tomado todavía.
- ¿ISO 8601 y RFC 3339 son lo mismo?
- No. La RFC 3339 se presenta como un perfil de ISO 8601 para protocolos de Internet, y un perfil es un subconjunto. Su gramática solo admite la fecha de calendario, exige que la hora y el desfase estén presentes, limita la hora entre 00 y 23, y escribe el desfase con dos puntos y minutos obligatorios. Así que una fecha desnuda, una fecha de semana como 2026-W33-4, una fecha ordinal como 2026-225, el formato básico sin guiones, una hora de 24 y un desfase escrito +0200 o +02 son todos ISO 8601 válida y ninguno es RFC 3339 válida. En sentido contrario, la RFC 3339 da a -00:00 un significado propio —se conoce la hora UTC pero no el desfase local— y permite t y z minúsculas. Cuando una API pide ISO 8601, envía RFC 3339 y satisfarás a las dos.
- ¿Por qué la herramienta muestra la fecha de ayer cuando pulso «Ahora»?
- Porque lee el reloj en UTC y fija el desfase en UTC+00:00, no porque haya contado mal. Si estás al este de Greenwich y es poco después de medianoche, tu reloj de pared ya está en el día nuevo mientras UTC sigue en el viejo. Un lector parisino que pulse «Ahora» a las 00:30 del 13 de agosto ve rellenados 12 de agosto y 22:30: el mismo momento, expresado en la zona por defecto de la herramienta. Nada de la conversión pasa por la zona horaria de tu máquina: el instante se guarda como enteros y se desplaza con aritmética entera, y cinco casos límite, incluidos una fecha anterior a la época y un desfase de +12:45, coincidieron exactamente con Date.UTC. Si quieres tu hora de pared, escribe la fecha y la hora y elige tu desfase en la lista.
- ¿De verdad puedo ordenar fechas ordenando el texto?
- Sí, con una condición: todas las cadenas deben tener la misma forma y el mismo desfase. Se ordenaron cinco instantes de ambas maneras con la herramienta y los órdenes fueron idénticos. Rompe la condición y falla en silencio: 2026-01-05T09:00:00Z se ordena antes que 2026-01-05T10:00:00+02:00 como texto, pero sus marcas son 1767603600 y 1767600000, así que el que va segundo ocurrió primero. Mezclar fechas civiles con fechas de semana lo rompe igual de mal, ya que 2026-W33-4 se compara con 2026-08-13 como dos cadenas sin significado común. Normaliza a Z y a una sola forma antes de ordenar, y el truco es completamente seguro, que es justo por lo que es la manera correcta de nombrar archivos.
- ¿Por qué el 1 de enero de 2027 se escribe 2026-W53-5?
- Porque una semana pertenece por entero a un solo año, y la norma se la da al que contiene su jueves. La semana que incluye el 1 de enero de 2027 tiene su jueves el 31 de diciembre de 2026, así que toda la semana es la semana 53 del año de numeración 2026, y el viernes que contiene es el día 5. La misma regla juega en sentido contrario: el 31 de diciembre de 2024 sale como 2025-W01-2, ambos verificados en la herramienta. Dos consecuencias prácticas. El año de numeración de semanas no es el año civil y nunca debe pegarse a un mes civil en un titular de informe. Y un año tiene 53 semanas cuando su 1 de enero cae en jueves, o en miércoles de año bisiesto —2026 tiene 53, 2027 tiene 52—, de modo que un gráfico con 52 columnas fijas descoloca una semana cada cinco o seis años.
Artículos que podrían interesarte
Todas las guías →Herramientas relacionadas
Todo lo que sigue describe lo que hacen hoy estas cuatro herramientas, comprobado ejecutando su propio código sobre las entradas exactas que aparecen en cada artículo, y no lo que una norma les obligue a hacer. Cuando una herramienta falla en un caso, queda escrito con claridad en vez de sortearlo, y no se ha cambiado nada para que un artículo se lea mejor. Dos consecuencias. Pasa cualquier transformación primero sobre una copia y compara los dos extremos: una herramienta de texto que borra algo no lo anuncia. Y da un secreto por compartido en cuanto sale de la página: pegarlo en una conversación, un ticket o un repositorio lo quema, por bien generado que estuviera.
Fuentes
- IETF — RFC 3339 — Date and Time on the Internet: Timestamps (§5.6 grammar, §4.3 unknown local offset)
- IETF — RFC 9557 — Timestamps with Additional Information, which extends RFC 3339 with a zone identifier
- WHATWG — HTML Standard — dates and times: the date, time and datetime microsyntaxes browsers accept
- MDN Web Docs — Date.prototype.toISOString() — the simplified extended format JavaScript emits
¿Has detectado un error en este artículo?