El comportamiento de zona horaria de cron - Dependencia oculta de la configuración del sistema
El demonio cron de Linux interpreta por defecto las programaciones usando la zona horaria del sistema (/etc/localtime o la variable de entorno TZ). Escribir «0 2 * * *» significa las 2:00 AM en la hora local del sistema. Esto funciona de forma intuitiva en un servidor único, pero en entornos donde múltiples servidores operan en diferentes zonas horarias o las instancias en la nube usan UTC por defecto, las tareas se ejecutan en horarios no previstos.
Las instancias de AWS EC2 usan UTC por defecto. Para ejecutar una tarea por lotes a las 2:00 AM hora de Japón, debes escribir «0 17 * * *» (UTC 17:00 = JST 2:00 del día siguiente). La conversión manual es propensa a errores, y las regiones con horario de verano añaden otra capa de complejidad que confunde aún más el cálculo.
Riesgos del horario de verano - Doble ejecución y saltos
Cuando cron opera en hora local en una región con horario de verano, los problemas surgen dos veces al año. En las transiciones de primavera (p. ej., las 2:00 AM saltan a las 3:00 AM), las tareas programadas entre las 2:00 y las 2:59 se saltan por completo. En las transiciones de otoño (p. ej., las 2:00 AM retroceden a la 1:00 AM), las tareas programadas entre la 1:00 y la 1:59 se ejecutan dos veces.
Una copia de seguridad de base de datos que se ejecute dos veces puede causar poco daño real, pero un lote de facturación o agregación que se ejecute dos veces es un problema grave. A la inversa, una tarea diaria crítica que se salta puede pasar desapercibida hasta el día siguiente. La solución fundamental es ejecutar cron en UTC, evitando el problema por completo.
Operación en UTC - El valor por defecto más seguro
Configurar la zona horaria del sistema en UTC y escribir las programaciones de cron en UTC es el patrón operativo más seguro. UTC no tiene horario de verano, por lo que ni la doble ejecución ni los saltos pueden ocurrir en principio. Para ejecutar algo a «las 2:00 AM hora de Japón», escribe «0 17 * * *» una vez y olvídalo; la tarea se ejecuta en el mismo instante UTC todo el año.
La operación en UTC también tiene inconvenientes. Una tarea que debe ejecutarse a «medianoche del primero de cada mes (JST)» se convierte en «15:00 del último día del mes anterior» en UTC. Como el último día varía entre 28 y 31, ninguna expresión cron fija lo captura perfectamente. Estas tareas necesitan iniciarse a una hora UTC fija y que su lógica interna verifique si el mes en JST ha cambiado.
Kubernetes CronJob - El campo timeZone
Kubernetes CronJob soporta el campo timeZone desde la versión 1.27 (GA). Configurar spec.timeZone con un nombre IANA como Asia/Tokyo hace que la programación se interprete en esa zona, eliminando la conversión manual a UTC y mejorando la legibilidad. Los ingenieros pueden escribir la programación tal como la conciben.
Incluso con timeZone, el comportamiento durante el horario de verano merece atención. El controlador de Kubernetes reconoce las transiciones, pero su manejo de los horarios saltados o duplicados puede variar según la versión. Para tareas de misión crítica, definir las programaciones en UTC y reservar timeZone para los casos donde la legibilidad importa más es el compromiso más seguro.
Planificadores en la nube - Soporte nativo de zona horaria
AWS EventBridge Scheduler, Google Cloud Scheduler y Azure Logic Apps soportan la especificación de zona horaria de forma nativa. AWS EventBridge acepta una zona horaria en la ScheduleExpression y gestiona las transiciones de horario de verano automáticamente. Sin embargo, cada servicio maneja de forma diferente el «horario inexistente durante el adelanto de primavera», por lo que conviene consultar la documentación del servicio específico en uso.
Sea cual sea el planificador que utilices, documenta la intención de cada programación en comentarios. «0 17 * * *» por sí solo no dice nada a los futuros mantenedores sobre si se pretende que sea UTC 17:00 o JST 2:00 expresado en UTC. Incluso la infraestructura como código se beneficia de comentarios explícitos que documenten la zona horaria prevista, del mismo modo que se documentaría la lógica de negocio en el código de aplicación.