Las marcas de tiempo Unix son uno de los formatos de datos más importantes en la programación — aparecen en registros de bases de datos, respuestas de APIs, archivos de registro, metadatos del sistema de archivos, tokens de autenticación e innumerables otros lugares. El formato es elegantemente simple: un solo entero que representa los segundos (o milisegundos, microsegundos o nanosegundos) desde el 1 de enero de 1970. Sin embargo, trabajar con marcas de tiempo correctamente es sorprendentemente complicado debido al manejo de zonas horarias, los desajustes de precisión entre sistemas y los casos límite del horario de verano. Las secciones siguientes explican qué es el tiempo Unix y por qué existe, cómo manejar correctamente las zonas horarias al convertir, y los errores comunes que atrapan a los desarrolladores incluso después de años de experiencia.

Qué Es el Tiempo Unix y Por Qué Existe

La hora Unix, también llamada hora de época o hora POSIX, es la cantidad de segundos transcurridos desde el 1 de enero de 1970 a las 00:00:00 UTC, un punto de referencia llamado época Unix. Los valores negativos representan fechas anteriores a esa época, los valores positivos representan fechas posteriores. El formato se originó a principios de la década de 1970, cuando los sistemas Unix necesitaban una forma compacta e independiente de la zona horaria para almacenar marcas de tiempo en metadatos del sistema de archivos y registros de registro. Un único entero de 32 bits con signo podría representar fechas de 1901 a 2038, lo que parecía suficiente en el momento del diseño, pero crea el famoso problema del año 2038 cuando ese rango expira. Los sistemas modernos utilizan números enteros de 64 bits, lo que lleva el vencimiento al año 292 mil millones. La elegancia del tiempo Unix es que no tiene zona horaria, ni horario de verano, ni segundos intercalares (oficialmente; la mayoría de las implementaciones simplemente difuminan los raros segundos intercalares) y no tiene complejidad de calendario. Es un contador monótonamente creciente que identifica sin ambigüedades un momento específico. Las zonas horarias, las fechas del calendario y los formatos legibles por humanos se superponen en el momento de la visualización. Esto hace que la hora de Unix sea el formato preferido para realizar comparaciones (`if (tokenExpiresAt < now)`), ordenar y almacenar marcas de tiempo en bases de datos en sistemas distribuidos que abarcan zonas horarias. Los formatos legibles por humanos como `2024-04-21 11:58:41` se derivan del valor almacenado de Unix solo cuando se muestran a un usuario.

Manejo de Zonas Horarias — La Parte Sutil

Una marca de tiempo de Unix en sí misma no tiene zona horaria; representa un momento específico en tiempo absoluto. Cuando convierte a un formato legible por humanos, elige una zona horaria para mostrar y la misma marca de tiempo produce diferentes horas locales en diferentes zonas. Por ejemplo, 1713711521 segundos después de la época son las 15:58:41 UTC, pero ese mismo momento es las 11:58:41 EDT (América/Nueva_York, UTC-4), las 08:58:41 PDT (América/Los_Angeles, UTC-7), las 00:58:41 JST del día siguiente (Asia/Tokio, UTC+9) y muchos otros veces alrededor del mundo. Hacer esto bien en la práctica requiere nombres de zonas horarias de la IANA como `America/New_York` en lugar de compensaciones fijas como `UTC-05:00`, porque los nombres de la IANA codifican el historial completo del horario de verano. Decir "4 p. m. EST el 15 de julio de 2024" es en realidad ambiguo porque la hora del este observa el horario de verano y las fechas de julio están en EDT (UTC-4), no en EST (UTC-5). Las zonas horarias de la IANA resuelven esta ambigüedad automáticamente: la API Intl del navegador y las bibliotecas del lado del servidor como pytz, moment-timezone y ZoneId de Java utilizan la base de datos de la IANA y manejan las transiciones históricas de DST correctamente. Este conversor utiliza el Intl.DateTimeFormat integrado en el navegador con compatibilidad total con la zona horaria de la IANA, lo que significa que produce horas locales correctas para cualquier zona válida, incluidas fechas históricas que se remontan a 1970 o antes.

Los Errores Comunes que Atrapan Incluso a Desarrolladores Experimentados

Un puñado de errores de marcas de tiempo aparecen tan a menudo que vale la pena interiorizarlos como una lista de verificación. Primero, la confusión entre segundos y milisegundos: el objeto Date de JavaScript trabaja en milisegundos mientras que time.time() de Python trabaja en segundos, y mezclarlos accidentalmente multiplica o divide tus fechas por 1000. Revisa la magnitud: los números de 10 dígitos son segundos, los de 13 dígitos son milisegundos, los de 16 dígitos son microsegundos. Segundo, la suposición de zona horaria al analizar: la cadena "2024-04-21 11:58:41" no tiene zona horaria, y distintos analizadores usan suposiciones predeterminadas diferentes. El constructor Date de JavaScript la trata como hora local; el datetime.fromisoformat de Python la trata como ingenua (sin zona horaria). Siempre adjunta una zona horaria explícita a las cadenas ambiguas antes de analizarlas. Tercero, los casos límite del horario de verano en las transiciones de primavera y otoño: las 2:30 AM del día en que se adelanta el reloj no existen en la mayoría de las zonas horarias de EE. UU. (el reloj salta de la 1:59 a las 3:00), y la 1:30 AM del día en que se retrasa el reloj existe dos veces. La aritmética de fechas que suma o resta horas a través de un límite del horario de verano puede producir resultados sorprendentes a menos que uses bibliotecas que consideran IANA. Cuarto, la deriva del "ahora" entre servidores: los relojes de los servidores se desvían por milisegundos o segundos, así que los tokens generados en un servidor y validados en otro necesitan una ventana de tolerancia. Quinto, los segundos intercalares: rara vez relevantes en la práctica porque la mayoría de los sistemas los reparten, pero críticos para aplicaciones científicas o financieras precisas. Este conversor evita la mayoría de estos al usar las bien probadas APIs Intl del navegador, pero los conceptos subyacentes siguen importando al escribir código que consume los valores convertidos.