Cómo convertir entre formatos horarios
Los formatos de tiempo varían entre sistemas, API y países. Marcas de tiempo Unix en respuestas de API, ISO 8601 en bases de datos, relojes de 12 horas en EE. UU., relojes de 24 horas en Europa: convertir entre ellos es una necesidad constante para desarrolladores y para cualquiera que trabaje con datos internacionales. Entender por qué existe cada formato, dónde brilla y dónde muerde convierte la conversión en un reflejo rápido en vez de una fuente recurrente de bugs sutiles.
Breve historia de los formatos de tiempo
Estandarizar el tiempo es más antiguo que internet. En 1884 la Conferencia Internacional del Meridiano estableció la hora media de Greenwich y el meridiano de origen, lo que dio al mundo una referencia común por primera vez. El reloj de 24 horas se extendió por la aviación y los militares por la misma razón: elimina la ambigüedad AM/PM que convierte una reserva de medianoche en un vuelo de mediodía.
El tiempo Unix llegó con el núcleo Unix original en 1971, contando segundos desde el 1 de enero de 1970 UTC (la "epoch"). La elección fue pragmática: un entero de 32 bits podía cubrir décadas, ordenar marcas de tiempo equivalía a ordenar números, y calcular intervalos era una resta. ISO 8601 llegó en 1988 para estandarizar el lado legible: año-mes-día en orden big-endian, T como separador fecha/hora y Z para UTC. RFC 3339 (2002) es un perfil más restrictivo de ISO 8601 diseñado para protocolos de internet. RFC 2822 (2001) define el formato estilo correo con nombres de día y offsets. Cada formato resuelve un problema real; ninguno reemplaza a los otros por completo.
Formatos de tiempo comunes
Seis formatos cubren casi todo lo que encontrarás en la práctica. La primera columna es el nombre que verás en la documentación; la columna de ejemplo muestra cómo se ve 14:30 del 7 de abril de 2024 UTC.
| Formato | Ejemplo | Usado por |
|---|---|---|
| Marca de tiempo Unix (segundos) | 1712502600 | API, bases de datos, tokens JWT, líneas de log |
| Marca de tiempo Unix (ms) | 1712502600000 | JavaScript, Java, Android |
| Marca de tiempo Unix (microsegundos) | 1712502600000000 | Postgres, Kafka, OpenTelemetry |
| ISO 8601 / RFC 3339 | 2024-04-07T14:30:00Z | API JSON, bases de datos, logs |
| RFC 2822 | Sun, 07 Apr 2024 14:30:00 +0000 | Cabeceras de correo, cabeceras HTTP |
| 24 horas | 14:30 | Europa, militar, aviación |
| 12 horas | 2:30 PM | EE. UU., uso informal |
| Día del año (juliano) | 2024-098 | Aviónica, datos científicos |
| Fecha por semana | 2024-W14-7 | Planificación industrial, banca |
La mayoría de los equipos se asientan en milisegundos Unix para almacenamiento e ISO 8601 para tránsito, con formatos de visualización elegidos por locale. La elección importa menos que la consistencia: elige un formato principal, documéntalo y convierte en los bordes.
Referencia rápida de conversión
12 horas a 24 horas
El reloj de 12 horas tiene dos rarezas: las 12 AM son medianoche (el inicio del día) y las 12 PM son el mediodía. La tabla siguiente cubre los casos que confunden a la gente.
| 12 horas | 24 horas |
|---|---|
| 12:00 AM (medianoche) | 00:00 |
| 1:00 AM | 01:00 |
| 11:59 AM | 11:59 |
| 12:00 PM (mediodía) | 12:00 |
| 12:01 PM | 12:01 |
| 1:00 PM | 13:00 |
| 6:00 PM | 18:00 |
| 11:59 PM | 23:59 |
Marcas de tiempo a fechas
El conversor epoch traduce instantáneamente marcas de tiempo Unix a fechas legibles y viceversa. El conversor detecta automáticamente los formatos de segundos (10 dígitos) y milisegundos (13 dígitos), así que puedes pegar un valor desde cualquier fuente sin preocuparte por la unidad.
Una comprobación de cordura útil: divide por 86400 (segundos en un día) y luego suma 1970 días para ubicar mentalmente cualquier marca de tiempo. 1712502600 / 86400 ~ 19820 días, unos 54 años después de 1970, lo que lo sitúa en 2024. No es preciso pero basta para detectar errores de factor 1000 de un vistazo.
Ejemplos de conversión en código
La mayoría de los desarrolladores eventualmente necesita convertir marcas de tiempo en código. Las API principales son cortas:
- JavaScript,
new Date(1712502600 * 1000).toISOString()devuelve2024-04-07T14:30:00.000Z. Recuerda multiplicar por 1000 porqueDatede JavaScript espera milisegundos. En sentido contrario:Math.floor(Date.now() / 1000)da una marca de tiempo en segundos. - Python,
datetime.fromtimestamp(1712502600, tz=timezone.utc).isoformat()devuelve2024-04-07T14:30:00+00:00. Evitautcfromtimestamp(); devuelve un datetime ingenuo que el resto de tu código tratará erróneamente como hora local. - Go,
time.Unix(1712502600, 0).UTC().Format(time.RFC3339)devuelve2024-04-07T14:30:00Z. El paquete time de Go es inusual pero consistente una vez interiorizado el diseño de referenciaMon Jan 2 15:04:05 MST 2006. - Shell,
date -u -d @1712502600 +"%Y-%m-%dT%H:%M:%SZ"en GNU/Linux, odate -u -r 1712502600 +"%Y-%m-%dT%H:%M:%SZ"en BSD/macOS. La diferencia de flag es uno de los traspiés multiplataforma más buscados en Google. - Rust,
chrono::DateTime::<chrono::Utc>::from_timestamp(1712502600, 0).unwrap().to_rfc3339()devuelve la misma cadena ISO. La biblioteca estándar ahora tieneSystemTimepero chrono sigue siendo la elección práctica para formatear. - SQL (Postgres),
SELECT to_timestamp(1712502600) AT TIME ZONE 'UTC';devuelve untimestamptz. MySQL usaFROM_UNIXTIME(); SQLite usadatetime(1712502600, 'unixepoch').
Una herramienta de conversión es más rápida que cualquiera de estos one-liners cuando solo necesitas traducir un valor, que es la mayor parte del tiempo durante la depuración.
Por qué ISO 8601 gana para almacenamiento
ISO 8601 (y el perfil RFC 3339) se ordena correctamente como cadena pura. 2024-04-07T14:30:00Z va alfabéticamente antes de 2024-04-07T15:00:00Z, que va antes de 2024-04-08T00:00:00Z. Esa propiedad te deja ordenar marcas de tiempo sin parsearlas, agrupar líneas de log con sort | uniq -c y razonar sobre rangos con simples comparaciones de cadenas.
También es inequívoco de una forma que los formatos regionales no son. 04/07/2024 podría ser 7 de abril (EE. UU.) o 4 de julio (la mayor parte de Europa); 2024-04-07 es lo mismo en todas las locales. Para el intercambio máquina a máquina, esa falta de ambigüedad vale más que cualquier otra consideración de formato.
Errores comunes a evitar
- Olvidar el huso horario,
2026-04-07 14:30es ambiguo sin huso. Incluye siempreZo un offset+00:00al almacenar cadenas ISO, y nunca confíes en el huso por defecto del lector. - Mezclar segundos y milisegundos, una marca de tiempo Unix de 10 dígitos es segundos, una de 13 dígitos es milisegundos. Mezclarlas produce fechas en 1970 o muy en el futuro. Microsegundos (16 dígitos) y nanosegundos (19 dígitos) también se cuelan, así que anticípalos.
- Confiar en la hora local en servidores, si tu servidor está en UTC y tu usuario en Tokio, almacena UTC y convierte en pantalla. Dejar que el servidor infiera la locale lleva casi siempre a bugs cuando los usuarios viajan o cambia el horario de verano.
- Parsear con aritmética de cadenas, no cortes ni concatenes cadenas de fecha. Usa
Date.parse(),dateutil.parser,chrono, o la biblioteca estándar de tu lenguaje. El parseo manual se rompe en fechas extremas, años bisiestos y offsets de huso. - Confiar en
new Date("2024-04-07"), JavaScript parsea cadenas solo-fecha como medianoche UTC, pero cadenas fecha-hora sin huso como medianoche local. El comportamiento difiere entre navegadores y versiones de Node. Incluye siempre unZu offset explícito. - Años de dos dígitos,
04/07/24podría ser 1924, 2024 o 2124 según la implementación. Usa años de cuatro dígitos en todas partes. - Transiciones de horario de verano, el reloj local salta una hora en primavera y repite una en otoño. Un planificador ingenuo puede ejecutar una tarea dos veces o ninguna esos días. Usa UTC para la lógica de planificación y convierte solo para mostrar.
- Segundos intercalares, el tiempo Unix finge que no existen suavizando o repitiendo el segundo afectado. El código que compara "segundos transcurridos" puede divergir brevemente de un reloj de pared que respete los segundos intercalares.
- El problema del año 2038, el
time_tcon signo de 32 bits desborda el 19 de enero de 2038. La mayoría de sistemas modernos usan tiempo de 64 bits, pero dispositivos embebidos heredados y columnas de base de datos antiguas aún pueden encontrarlo. Audita allí donde veasINT4oint32usado para almacenar marcas de tiempo. - Formato dependiente de locale,
toLocaleString()en JavaScript y funciones equivalentes en otros lenguajes producen salida diferente en máquinas diferentes. Para marcas de tiempo legibles por máquina, usatoISOString()o equivalente; para mostrar, formatea explícitamente.
Herramientas y bibliotecas alternativas
Un conversor maneja el caso puntual; para código de producción acudirás a una biblioteca.
| Herramienta / biblioteca | Lenguaje | Fortaleza | A tener en cuenta |
|---|---|---|---|
| Conversor web | Navegador | Instantáneo, sin instalación, maneja ambigüedades comunes | Un valor a la vez |
dateutil | Python | Parser tolerante, consciente de husos | Más lento que datetime para trabajo masivo |
arrow | Python | API amigable, defaults ISO | Dependencia extra para proyectos pequeños |
date-fns | JavaScript | Tree-shakable, inmutable | Cada función es su propio import |
dayjs | JavaScript | Pequeño, API compatible con moment | Modelo de plugins para extras |
luxon | JavaScript | Husos IANA de primera clase | Bundle más grande |
chrono | Rust | Tipos ricos, RFC 3339 nativo | Ritmo de mantenimiento variable |
Joda-Time / java.time | Java | El diseño de referencia que influyó en los demás | Evita los legacy Date y Calendar |
NodaTime | C#/.NET | Instantes, duraciones y calendarios bien separados | Migrar desde DateTime no es trivial |
GNU date | Shell Linux | Parseo flexible con -d | BSD/macOS usa flags incompatibles |
La biblioteca correcta depende de tu stack; la disciplina correcta es la misma en todas partes: almacena UTC, transmite ISO 8601, formatea solo para mostrar y nunca confíes en una marca de tiempo sin huso explícito.
Privacidad y el conversor
El conversor de formatos de tiempo corre enteramente en tu navegador. Las marcas de tiempo que pegas y las fechas que generas nunca salen de la página. No hay registro en servidor de qué valores se convirtieron, ni analítica sobre qué formatos son populares, ni manera de que nadie ligue una solicitud a tu IP. Las conversiones de tiempo no son datos personales en sí, pero las marcas de tiempo en tus logs (horas de inicio de sesión, horas de transacción, ventanas de planificación) a menudo lo son, y pasarlas por un conversor de terceros podría filtrar detalles operativos. Hacer el trabajo del lado del cliente mantiene esa información en tu máquina donde pertenece. Para una tarea tan rutinaria como pasar entre segundos e ISO 8601, el ajuste de privacidad por defecto debería ser sin transmisión, sin registro, sin terceros en el bucle.
Preguntas frecuentes
¿Qué es el formato ISO 8601?
ISO 8601 es el estándar internacional para representar fechas y horas. Se parece a 2026-04-07T14:30:00Z, donde T separa la fecha y la hora, y Z indica UTC. No es ambiguo sea cual sea el idioma.
¿Por qué las API usan marcas de tiempo Unix en lugar de fechas legibles?
Las marcas de tiempo Unix son un único número, fácil de guardar, ordenar y comparar. Son neutrales respecto a la zona horaria (siempre UTC) y ocupan menos espacio que una cadena de fecha formateada. El compromiso: no son legibles para un humano.
¿Qué significa la Z al final de una marca de tiempo?
La Z significa «Zulu time», otro nombre para UTC (Coordinated Universal Time). Una marca de tiempo terminada en Z está en UTC, no en hora local.
¿Cómo convertir una hora 24 h a 12 h?
Para horas de 1 a 12, la hora se mantiene (añade AM para 0-11, PM para 12). Para 13-23, resta 12 y añade PM. 00:00 pasa a 12:00 AM (medianoche). 12:00 pasa a 12:00 PM (mediodía).
What is the Year 2038 problem?
32-bit signed Unix timestamps overflow on 19 January 2038 at 03:14:07 UTC, after which they wrap around to negative values that look like dates in 1901. Most modern systems use 64-bit timestamps and are unaffected, but legacy embedded devices, old databases, and 32-bit time_t in some C code still need to be audited.
How are leap seconds handled in Unix time?
Unix time pretends leap seconds do not exist. The clock simply repeats or stretches the affected second, so a Unix timestamp is not a strict count of elapsed SI seconds. For most applications this is fine, but precision-timing code (astronomy, GPS, high-frequency trading) needs TAI or UTC with explicit leap-second handling.