Sin subida, 100% local, sin cuenta

Artículo

Timestamps Unix y expresiones cron explicados

Un timestamp Unix es solo un entero. Una expresión cron son solo cinco campos. Ambos aparecen constantemente en el trabajo de backend, y ambos generan confusión de maneras predecibles: uno por las zonas horarias, el otro por la unidad.

Qué es un timestamp Unix

Un timestamp Unix cuenta el número de segundos transcurridos desde el 1970-01-01 00:00:00 UTC, un punto de referencia conocido como el epoch Unix. Esa definición tiene dos consecuencias importantes. Primera, el conteo está en UTC: no hay ninguna zona horaria incorporada en el número en sí. 1718400000 significa el mismo instante en cualquier lugar de la Tierra, independientemente de dónde esté la máquina que lo almacena. Segunda, el epoch está definido en segundos, no en ninguna otra unidad. Un valor como 1718400000 son siempre segundos desde la medianoche del 1 de enero de 1970 UTC, a menos que un sistema o protocolo haya tomado una decisión diferente de forma explícita. Los timestamps están libres de zona horaria por diseño, lo que es precisamente la razón por la que son útiles para registros, bases de datos y comunicación entre sistemas donde los relojes de distintas regiones deben referirse al mismo momento sin ambigüedad.

Línea temporal que muestra el epoch Unix en 1970-01-01 00:00:00 UTC a la izquierda, un timestamp actual en el centro y el límite de desbordamiento de 2038 a la derecha, marcado con el máximo del entero con signo de 32-bit.

Segundos, milisegundos y el problema del año 2038

Muchos entornos de ejecución y APIs modernos usan milisegundos en lugar de segundos. Date.now() de JavaScript devuelve milisegundos, por lo que 1718400000000 es el mismo instante que el valor de precisión de segundos 1718400000. Cuando recibes un timestamp desconocido, la magnitud te indica la unidad: un número de 10 dígitos casi siempre son segundos; un número de 13 dígitos casi siempre son milisegundos. El problema del año 2038 surge de una elección diferente: almacenar un timestamp de precisión de segundos en un entero con signo de 32-bit. El valor máximo de un entero con signo de 32-bit es 2147483647, que corresponde a 2038-01-19 03:14:07 UTC. Tras ese segundo, el contador desborda a un número negativo grande y la fecha vuelve a 1901 en los sistemas que no gestionan el límite. La solución es usar almacenamiento de 64 bits. La mayoría de los sistemas operativos y bases de datos actuales ya lo hacen, pero los sistemas embebidos, los dispositivos de red y los formatos de archivo antiguos que fijaron el ancho de campo hace décadas siguen en riesgo.

Convertir epoch a una fecha legible: el paso de la zona horaria

Convertir un valor epoch a una fecha legible requiere dos pasos: obtener los componentes de la fecha UTC del entero y luego aplicar un desplazamiento UTC para obtener la hora local. El timestamp en sí está en UTC. Cuando preguntas qué fecha representa 1718325000, la respuesta correcta es 2024-06-14 a las 00:30 en UTC. En Nueva York (UTC-4 en verano), ese mismo segundo cae el 2024-06-13 a las 20:30 de la tarde anterior: la fecha cambia, no solo la hora. Este es el paso que produce resultados incorrectos cuando se omite: un desarrollador registra el timestamp bruto en UTC, una herramienta de informes lo renderiza en hora local sin conversión y la fecha parece estar desfasada unas horas o un día completo. La herramienta de conversión de timestamps de Sunasty gestiona esto de forma explícita: introduces un valor epoch y muestra la fecha y hora en UTC junto a la fecha y hora local de tu propio dispositivo, de modo que un cruce de día como este se ve de un vistazo. La conversión se ejecuta por completo en el navegador y nada de lo que pegas se envía a ningún sitio.

Dos cuadrículas de calendario una junto a la otra para el mismo valor epoch: la cuadrícula UTC resalta un día del calendario y la cuadrícula de Nueva York (UTC-4) resalta el día anterior, mostrando cómo la fecha local retrocede debido al desfase horario.

Sintaxis cron: cinco campos, rangos, pasos y listas

Una expresión cron programa trabajos recurrentes en sistemas tipo Unix. La sintaxis estándar tiene cinco campos separados por espacios: minuto (0-59), hora (0-23), día del mes (1-31), mes (1-12), día de la semana (0-7, donde tanto 0 como 7 representan el domingo). Un asterisco (*) en un campo significa «cada valor válido». La expresión 30 8 * * 1-5 se ejecuta a las 08:30 de lunes a viernes. Los rangos usan un guion: 1-5 cubre los valores 1, 2, 3, 4, 5. Las listas usan comas: 1,15 significa el día 1 y el 15. Los pasos usan barra: */15 en el campo de minutos significa cada 15 minutos (0, 15, 30, 45). Estos combinadores pueden aparecer juntos: 0-30/10 significa 0, 10, 20, 30. Una cosa que cron no tiene es un campo de zona horaria. El daemon lee el reloj de la máquina en la que se ejecuta, que está configurado con la zona horaria local del servidor. Si el servidor funciona en UTC pero el desarrollador espera hora local, el trabajo se ejecuta a una hora incorrecta del reloj. La regla práctica es tratar los programas cron como expresiones en hora-local-del-servidor y documentar la zona horaria del servidor junto a la línea cron.

Usar el conversor de timestamps localmente

El timestamp-converter de Sunasty convierte en ambas direcciones: epoch a fecha legible y fecha legible de vuelta a epoch. Puedes introducir un valor de precisión de segundos o de milisegundos; la herramienta detecta la unidad por la magnitud. Muestra el resultado en UTC y en la zona horaria local de tu propio dispositivo lado a lado, junto con los valores en bruto de segundos y milisegundos listos para copiar. Un botón Ahora rellena el timestamp actual con un clic, lo que resulta útil como referencia rápida cuando necesitas saber cuál es el tiempo Unix actual sin abrir una terminal. No hay un selector de zona horaria independiente: la columna local siempre refleja la zona horaria que tenga configurada tu navegador en cada momento. Todo esto se ejecuta en el navegador. El valor que pegas en el campo lo lee JavaScript en el lado del cliente y nunca abandona el dispositivo.

Herramientas en este artículo

Preguntas frecuentes

¿Por qué JavaScript usa milisegundos en lugar de segundos?

El objeto Date de JavaScript se diseñó para trabajar con precisión de subegundos desde el principio, y los milisegundos ofrecen mil veces la resolución de los segundos sin necesitar un punto decimal. La contrapartida es que los valores son más grandes, lo cual explica por qué Date.now() produce un número de 13 dígitos mientras que la mayoría de los timestamps del lado del servidor tienen 10 dígitos.

¿Necesita estar en UTC cada servidor que ejecuta cron?

No, pero ejecutar los servidores en UTC es una práctica habitual precisamente porque elimina la ambigüedad. Cuando un servidor está en UTC, una expresión cron como 0 2 * * * significa 02:00 UTC y esa hora es estable todo el año. En un servidor en una zona que observa el horario de verano, el mismo trabajo se ejecuta en un instante UTC diferente en verano y en invierno, y puede ejecutarse dos veces o saltarse una al cambiar el reloj.

¿Cuál es el tipo de almacenamiento seguro para timestamps posteriores a 2038?

Un entero con signo de 64 bits almacena timestamps de precisión de segundos hasta el año 292277026596, lo que está muy más allá de cualquier preocupación práctica. La mayoría de las bases de datos actuales almacenan los timestamps como valores de 64 bits por defecto. Si trabajas con un esquema heredado o un formato de archivo binario que usa campos de 32 bits, migrar a almacenamiento de 64 bits antes del límite de 2038 es la solución correcta.