Skip to content

Guide

Epoch, ISO 8601 o RFC 3339: ¿qué formato para una API?

Tres formatos para el mismo instante, y solo uno de ellos no es ambiguo sin leer la documentación.

By Published

Toda API que toca fechas termina teniendo que responder una pregunta: ¿cómo se ve realmente un campo de timestamp en el cable? Hay en realidad tres candidatos de uso habitual —un entero de epoch Unix en bruto, una cadena ISO 8601, y su prima más estricta RFC 3339. Todos describen el mismo instante en el tiempo, pero fallan de forma distinta cuando algo aguas abajo lo interpreta mal, y elegir el correcto desde el principio evita toda una categoría de reportes de error de «por qué esta fecha está desfasada unas horas» más adelante.

Qué es realmente cada formato

Un timestamp epoch Unix es un entero: el número de segundos (o milisegundos, o menos habitualmente microsegundos o nanosegundos) desde 1970-01-01T00:00:00Z, según la definición POSIX de time_t. No lleva zona horaria —siempre es relativo a UTC por construcción— pero tampoco lleva marcador de unidad, que es de donde viene la mayor parte de sus problemas reales.

ISO 8601 es el estándar internacional para representar fechas y horas como texto, y es deliberadamente amplio: permite fechas de calendario, fechas de numeración de semana, fechas ordinales, duraciones, intervalos, precisión reducida (solo un año, o un año y un mes), y valores de hora con o sin desfase UTC. Esa flexibilidad es exactamente lo que hace que «compatible con ISO 8601» sea una garantía más débil de lo que suena —dos sistemas pueden ser ambos técnicamente compatibles y aun así producir cadenas que el otro no puede analizar.

RFC 3339 es el perfil de internet del IETF de ISO 8601: mantiene exactamente una forma (YYYY-MM-DDTHH:MM:SS[.ffffff](Z|±HH:MM)) y elimina todo lo que ISO 8601 permite que haría ambiguo el análisis automático —sin fechas de semana, sin precisión reducida, y un desfase es obligatorio, nunca implícito. Cuando la gente dice «timestamp ISO 8601» en un contexto de API, lo que casi siempre quiere decir, y lo que casi siempre espera su código, es RFC 3339.

FormatoEjemplo¿Autodescriptivo?Riesgo de ambigüedad
Epoch (segundos)1700000000NoAlto — unidad no marcada
Epoch (milisegundos)1700000000000NoAlto — unidad no marcada
ISO 8601 (general)2023-11-14T22:13:20ParcialmenteMedio — el desfase puede omitirse
RFC 33392023-11-14T22:13:20ZSíBajo — desfase obligatorio, una forma

Dónde falla realmente cada uno

Los enteros epoch fallan en silencio, que es peor que fallar ruidosamente. 1700000000 es un número perfectamente válido tanto si significa segundos (14 de noviembre de 2023) como milisegundos (20 de enero de 1970) —una suposición de unidad equivocada no lanza un error, solo produce una fecha que está mal por órdenes de magnitud y parece plausible hasta que alguien lo nota. Este es el error de timestamp más común en sistemas que pasan valores epoch entre servicios escritos en lenguajes distintos, cada uno con su propia unidad predeterminada.

Las cadenas ISO 8601 simples fallan en el desfase. Una cadena como 2023-11-14T22:13:20 sin Z ni ±hh:mm es ISO 8601 válida pero genuinamente ambigua —¿es UTC, hora local del servidor, o la hora local del usuario de origen? Cada consumidor tiene que adivinar o consultar documentación fuera de banda, y distintos consumidores a veces adivinan de forma distinta.

RFC 3339 evita en gran parte ambos modos de fallo por construcción, por lo que es la recomendación predeterminada en las guías de estilo de API —el AIP-142 de Google, por ejemplo, lo exige para los campos de timestamp en APIs nuevas. Su caso límite restante es la precisión de fracción de segundo: la especificación permite cualquier número de dígitos tras el punto decimal, así que un productor que emite precisión de nanosegundo y un consumidor que trunca a milisegundo aún pueden discrepar sobre el instante exacto, solo que por un margen mucho más pequeño que un desajuste de unidad.

Elegir un formato para un campo nuevo

Para una API pública o entre servicios, opta por defecto por una cadena RFC 3339. Es legible en logs y depuradores en bruto sin decodificar, no es ambigua ni en la zona horaria ni en la precisión, y prácticamente cualquier biblioteca de fechas de lenguaje habitual la analiza y emite de forma nativa. El único coste son unos pocos bytes extra por valor comparado con un entero —irrelevante para casi cualquier payload de API.

Recurre a un entero epoch cuando el campo sea telemetría de alto volumen, un timestamp de métricas, o una clave interna de ordenación donde tanto el productor como el consumidor están bajo tu control y ya están de acuerdo en la unidad. Incluso entonces, documenta la unidad explícitamente en el nombre del campo (created_at_ms, no solo created_at) en lugar de confiar en la convención. Nuestra guía de timestamps Unix explicados cubre cómo funciona la detección de unidad basada en el número de dígitos cuando tienes que hacer ingeniería inversa de un campo epoch sin documentar.

La versión corta

Los enteros epoch son compactos pero no llevan unidad; el ISO 8601 simple es amplio pero puede omitir el desfase; RFC 3339 es la porción estrecha y no ambigua de ISO 8601 que la mayoría de las herramientas de API realmente esperan cuando dicen «fecha ISO». Si estás diseñando un campo nuevo y no tienes una razón de peso para optimizar el tamaño del payload, RFC 3339 elimina toda una categoría de errores de timestamp entre servicios antes de que puedan empezar.

Frequently asked questions

¿RFC 3339 es lo mismo que ISO 8601?
RFC 3339 es un perfil más estricto de ISO 8601, no un formato separado. Elige una única representación no ambigua entre las muchas que permite ISO 8601 — siempre un año de 4 dígitos, siempre un desfase UTC explícito (Z o ±hh:mm), sin fechas de numeración de semana, sin fechas de precisión reducida como solo «2026». Cualquier timestamp RFC 3339 es ISO 8601 válido; lo contrario no está garantizado.
¿Una API nueva debería usar enteros epoch o un timestamp de tipo cadena?
Para un campo nuevo, prefiere una cadena RFC 3339. Es autodescriptiva (una línea de log o un depurador muestra la fecha real, no un número de 10 dígitos que hay que decodificar), viaja de ida y vuelta entre lenguajes sin un acuerdo implícito de unidad, y lleva su propio desfase UTC. Los enteros epoch se ganan su lugar cuando el tamaño del payload importa (telemetría, métricas de alta frecuencia) o cuando un campo es puramente una duración interna o una clave de ordenación.
¿Por qué los errores de timestamp a menudo se reducen a segundos vs. milisegundos?
Porque un entero epoch no lleva ningún marcador de unidad — 1700000000 es silenciosamente válido tanto como una fecha de 2023 (segundos) como una fecha de 1970 (milisegundos), así que una suposición equivocada no da error, simplemente produce una fecha equivocada pero de aspecto plausible. Un formato de cadena esquiva toda esta categoría de error porque la precisión queda escrita: 2023-11-14T22:13:20.500Z es evidentemente de subsegundo.
¿RFC 3339 exige UTC?
No — exige un desfase explícito, que puede ser Z (UTC) o cualquier valor ±hh:mm. Lo que prohíbe es omitir el desfase por completo, algo que ISO 8601 técnicamente permite y que es la mayor fuente de ambigüedad de «¿esto es local o UTC?» en cadenas de fecha poco tipadas.

Sources & references

Authoritative references cited by this piece. Verified by Buğra Sözeri on the dates shown and re-checked at every deploy.

Related

Published September 25, 2026