Qué hace un conversor de Unix Timestamp (y por qué lo necesitas)
Un conversor de Unix timestamp traduce entre fechas legibles para humanos y el número de segundos desde el 1 de enero de 1970 a las 00:00:00 UTC (el "epoch de Unix"). Ahora mismo, mientras escribo esto, el timestamp es aproximadamente 1,780,000,000. Ese número aumenta en 1 cada segundo, nunca se reinicia y no le importan las zonas horarias, el horario de verano ni los años bisiestos. Es la forma más simple posible de representar un momento en el tiempo.
¿Por qué los desarrolladores necesitan un conversor? Porque los humanos pensamos en "4 de junio de 2026 a las 3:30 PM" y las computadoras piensan en 1780646400. Cada API, base de datos y archivo de log usa un formato u otro (o ambos). Convertir entre ellos a mano requiere saber el offset de zona horaria, si el horario de verano está activo y cuántos segundos tiene cada mes. O puedes usar una herramienta de conversión y obtener la respuesta en milisegundos.
El epoch de Unix (1 de enero de 1970) fue elegido arbitrariamente por los creadores de Unix en Bell Labs. No tiene significado astronómico ni histórico. Otros sistemas usan epochs diferentes: Windows FILETIME cuenta intervalos de 100 nanosegundos desde el 1 de enero de 1601. macOS Cocoa cuenta segundos desde el 1 de enero de 2001. El tiempo GPS cuenta semanas y segundos desde el 6 de enero de 1980. Convertir entre estos requiere conocer tanto el epoch como la unidad.
Segundos vs milisegundos (la fuente #1 de bugs)
Los Unix timestamps tradicionalmente cuentan segundos. Date.now() de JavaScript devuelve milisegundos. System.currentTimeMillis() de Java devuelve milisegundos. time.time() de Python devuelve segundos (como float). Esta inconsistencia causa bugs constantemente. Si ves un timestamp de 1780646400, son segundos (junio 2026). Si ves 1780646400000, son milisegundos (el mismo momento). Si accidentalmente tratas milisegundos como segundos, obtienes una fecha en el año 58,400.
La verificación rápida: si el número tiene 10 dígitos, son segundos (válido de 2001 a 2286). Si tiene 13 dígitos, son milisegundos (válido de 2001 a 2286). Si tiene 16 dígitos, son microsegundos (datetime.timestamp() de Python con precisión de microsegundos). Nuestra herramienta timestamp-converter auto-detecta la unidad basándose en el número de dígitos.
Mi regla: siempre almacena timestamps en milisegundos (o en formato de cadena ISO 8601). Los milisegundos te dan precisión sub-segundo sin los problemas de punto flotante de los segundos fraccionarios. Cada lenguaje moderno puede manejar enteros de 64 bits, así que el costo de almacenamiento es el mismo. Cuando te conectes con APIs que usan segundos, multiplica/divide por 1000 en el límite — no dejes que las unidades mixtas se propaguen por tu código.
Un bug que me pasó en 2021: un sistema de pagos almacenaba "created_at" en segundos pero la verificación del webhook comprobaba "el timestamp está dentro de 5 minutos del ahora" usando milisegundos. La verificación siempre fallaba porque la diferencia era 1,780,000,000,000 milisegundos (el timestamp en segundos, interpretado como milisegundos = año 58,400) menos el tiempo actual. Tomó 3 horas encontrarlo porque el mensaje de error solo decía "timestamp expired."
Bugs de zona horaria que le pasan a todo desarrollador
El bug de zona horaria más común: almacenar hora local sin información de zona horaria. Si tu base de datos tiene "2026-06-04 15:30:00" — ¿es UTC? ¿Hora del este? ¿La zona horaria del servidor? Si el servidor se mueve a una zona horaria diferente (o migras a otra región de la nube), todos tus timestamps se desplazan. Siempre almacena UTC y convierte a hora local solo para mostrar.
El horario de verano crea tiempos imposibles y ambiguos. El 3 de noviembre de 2024 a las 2:00 AM hora del este, los relojes retrocedieron a la 1:00 AM. La hora "1:30 AM" ocurrió dos veces. El 10 de marzo de 2024 a las 2:00 AM, los relojes saltaron a las 3:00 AM. La hora "2:30 AM" nunca existió. Si tu sistema de programación crea un evento a las 2:30 AM en un día de adelanto de reloj, ¿qué pasa? La mayoría de los sistemas lo mueven silenciosamente a las 3:30 AM. Algunos se caen.
El bug del "límite del día": "los pedidos de hoy" significa cosas diferentes en diferentes zonas horarias. Si tu servidor está en UTC y un usuario en California hace un pedido a las 11 PM Pacífico (7 AM UTC del día siguiente), aparece en el reporte de "mañana". Solución: siempre filtra por los límites del día local del usuario convertidos a UTC. Almacena la zona horaria del usuario (formato IANA como "America/Mexico_City", no offsets UTC que no consideran el horario de verano).
El objeto Date de JavaScript es consciente de zonas horarias pero confuso. new Date("2026-06-04") se parsea como medianoche UTC, pero new Date("2026-06-04T00:00:00") se parsea como hora local. new Date(2026, 5, 4) usa hora local (y los meses son base 0, así que 5 = junio). Esta inconsistencia ha causado más bugs que cualquier otra API de JavaScript. Usa la API Temporal (Stage 3, disponible en polyfills) o librerías como date-fns con manejo explícito de zonas horarias.
// The timezone trap in JavaScript
new Date("2026-06-04"); // UTC midnight
new Date("2026-06-04T00:00:00"); // LOCAL midnight (different!)
new Date(2026, 5, 4); // LOCAL midnight, month 5 = June
// Safe approach: always be explicit about timezone
new Date("2026-06-04T00:00:00Z"); // UTC (the Z matters)
new Date("2026-06-04T00:00:00+08:00"); // Beijing time
// Converting timestamp to readable date
const ts = 1780646400;
new Date(ts * 1000).toISOString(); // "2026-06-04T12:00:00.000Z"
new Date(ts * 1000).toLocaleString("es-MX", {
timeZone: "America/Mexico_City"
}); // "4/6/2026, 6:00:00 a. m."El problema del año 2038 (es real)
Un entero con signo de 32 bits puede contener valores hasta 2,147,483,647. Esa cantidad de segundos después del epoch de Unix es el 19 de enero de 2038 a las 03:14:07 UTC. Después de ese momento, los timestamps de 32 bits se desbordan a números negativos, volviendo al 13 de diciembre de 1901. Este es el problema Y2K para sistemas Unix, y está a 12 años de distancia.
Qué está afectado: sistemas embebidos (dispositivos IoT, computadoras de autos, controladores industriales), bases de datos antiguas con columnas de timestamp de 32 bits, programas en C que usan time_t como int de 32 bits, y formatos de archivo que almacenan timestamps de 32 bits (sistema de archivos ext3, algunas implementaciones de ZIP). El kernel de Linux cambió a time_t de 64 bits para arquitecturas de 32 bits en el kernel 5.6 (2020), pero programas de espacio de usuario compilados contra librerías antiguas pueden seguir usando time de 32 bits.
Qué NO está afectado: cualquier sistema de 64 bits (todos los servidores, escritorios y teléfonos modernos), JavaScript (usa floats de 64 bits para timestamps), Python (enteros de precisión arbitraria), Java (long es de 64 bits), PostgreSQL (el tipo timestamp es de 64 bits). Si estás escribiendo una aplicación web en 2026, casi seguro estás bien. El riesgo está en sistemas embebidos y código legacy que no se actualizará antes de 2038.
Si mantienes sistemas legacy: audita tu almacenamiento de timestamps. El tipo TIMESTAMP de MySQL era de 32 bits hasta MySQL 8.0.28 (2022) — versiones anteriores se desbordarán en 2038. SQLite almacena timestamps como texto o enteros de 64 bits (seguro). Revisa cualquier código C/C++ que use time_t — en plataformas de 32 bits, puede seguir siendo de 32 bits. La solución suele ser recompilar con _TIME_BITS=64 o migrar a plataformas de 64 bits.
Almacenamiento de timestamps en bases de datos
PostgreSQL: Usa TIMESTAMPTZ (timestamp with time zone). A pesar del nombre, no almacena una zona horaria — almacena UTC y convierte a/desde la zona horaria de la sesión en entrada/salida. TIMESTAMP simple (sin zona horaria) almacena lo que le des sin conversión, lo que lleva a ambigüedad. Siempre usa TIMESTAMPTZ.
MySQL: TIMESTAMP almacena UTC (4 bytes, rango 1970-2038 en versiones antiguas, extendido en 8.0.28+). DATETIME almacena el valor literal sin conversión de zona horaria (8 bytes, rango 1000-9999). Usa TIMESTAMP para "cuándo pasó esto" (auto-convierte a UTC) y DATETIME para "programado para esta fecha/hora exacta sin importar la zona horaria" (como un cumpleaños o una reunión en una zona horaria específica).
MongoDB: El tipo Date almacena milisegundos desde el epoch como un entero de 64 bits. Internamente siempre es UTC. El helper ISODate() del shell es solo azúcar sintáctica para new Date(). Almacena todas las fechas como objetos Date, no como strings. Las fechas en string no se pueden indexar eficientemente y los operadores de comparación no funcionarán correctamente entre zonas horarias.
Consejo general: almacena timestamps UTC, almacena la zona horaria del usuario por separado (como un string de zona horaria IANA como "America/Bogota"), y calcula la hora local de visualización en la capa de aplicación. Nunca almacenes strings de fecha pre-formateados — pierdes la capacidad de re-formatear para diferentes locales o recalcular cuando las reglas de zona horaria cambien (lo cual pasa más seguido de lo que crees — los gobiernos cambian las reglas del horario de verano regularmente).
Segundos intercalares (el caso borde que rompe cosas)
La rotación de la Tierra se está desacelerando, así que UTC ocasionalmente agrega un "segundo intercalar" para mantenerse sincronizado con el tiempo astronómico. Cuando esto pasa, el tiempo 23:59:60 existe por un segundo antes de medianoche. Los Unix timestamps manejan esto repitiendo un segundo (el reloj muestra el mismo timestamp dos veces) o "untando" el segundo intercalar sobre un período más largo (el enfoque de Google: distribuirlo en 24 horas para que cada segundo sea ligeramente más largo).
En la práctica, los segundos intercalares han causado caídas reales. Reddit se cayó por 30 minutos durante el segundo intercalar de junio de 2012 porque el manejo del reloj del kernel de Linux tenía un bug que causaba alto uso de CPU. Cloudflare tuvo una breve caída en enero de 2017 cuando su software RRDNS calculó una duración de tiempo negativa durante el segundo intercalar. Estos bugs son raros pero espectaculares.
La buena noticia: la Oficina Internacional de Pesas y Medidas (BIPM) votó en 2022 para abolir los segundos intercalares para 2035. Hasta entonces, hay 27 segundos intercalares acumulados desde 1972. La mayoría de los sistemas modernos usan NTP (Network Time Protocol) que maneja los segundos intercalares de forma transparente. Si estás construyendo un sistema que necesita precisión sub-segundo a través de límites de segundos intercalares (trading financiero, instrumentos científicos), usa TAI (Tiempo Atómico Internacional) que no tiene segundos intercalares.
Para la mayoría de los desarrolladores: ignora los segundos intercalares. La librería estándar de tu lenguaje los maneja (o pretende que no existen, lo cual está bien para el 99.99% de las aplicaciones). No intentes contabilizarlos manualmente. La única vez que lo notarás es si estás calculando duraciones exactas a través de un límite de segundo intercalar y obtienes 61 segundos en un "minuto" — lo cual es técnicamente correcto.
Patrones prácticos para trabajar con timestamps
Patrón 1: Respuestas de API. Devuelve strings ISO 8601 con offset de zona horaria: "2026-06-04T15:30:00-06:00" o UTC con sufijo Z: "2026-06-04T07:30:00Z". No devuelvas Unix timestamps crudos en APIs orientadas al usuario — son ilegibles sin un conversor. Las APIs internas servicio-a-servicio pueden usar timestamps en milisegundos por eficiencia.
Patrón 2: Programar eventos futuros. Almacena la hora local prevista Y la zona horaria: {time: "2026-12-25T09:00:00", timezone: "America/Mexico_City"}. No pre-conviertas a UTC porque si las reglas de zona horaria cambian (un gobierno mueve las fechas del horario de verano), tu hora UTC almacenada se vuelve incorrecta. Convierte a UTC en el momento de ejecución usando la base de datos de zonas horarias más reciente.
Patrón 3: Logs de auditoría y event sourcing. Usa timestamps monótonos (no tiempo de reloj de pared) para ordenar eventos dentro de un solo proceso. Los relojes de pared pueden saltar hacia atrás (correcciones NTP, migraciones de VM, segundos intercalares). Para ordenamiento entre máquinas, usa relojes lógicos (timestamps de Lamport, relojes vectoriales) o timestamps sincronizados con error acotado (TrueTime de Google Spanner, AWS Time Sync).
Patrón 4: Cálculos de edad. No restes timestamps y dividas por segundos-por-año (365.25 × 86400). Esto falla para años bisiestos, transiciones de horario de verano y diferencias de zona horaria. Usa una librería de fechas apropiada que calcule diferencias de calendario: differenceInYears() de date-fns, relativedelta de Python, o nuestra herramienta age-calculator que maneja todos estos casos borde correctamente.