Ir al contenido principal
Tecnología

Horario de verano en el código - Los errores y cómo evitarlos

Saltos y solapamientos - Las dos anomalías del cambio horario

Las transiciones del horario de verano rompen la continuidad temporal dos veces al año. En el adelanto de primavera (por ejemplo, en la zona Este de EE.UU. a las 2:00 AM saltando a las 3:00 AM), las horas de 2:00 a 2:59 simplemente no existen (un salto). En el atraso de otoño (las 2:00 AM retrocediendo a la 1:00 AM), las horas de 1:00 a 1:59 ocurren dos veces (un solapamiento). Estas dos anomalías generan una lista notablemente larga de errores de software.

Si un usuario introduce una hora dentro de un salto (digamos, 2:30 AM EST en el día de transición de primavera), el comportamiento correcto no es obvio. ¿Rechazarlo como error de validación? ¿Redondearlo hacia adelante a las 3:30 AM EDT? ¿Redondearlo hacia atrás a la 1:30 AM EST? Cada opción tiene méritos. El riesgo es que muchas bibliotecas eligen silenciosamente una opción y sorprenden a los desarrolladores que esperaban otra.

Aritmética de duración - 24 horas después no es mañana a la misma hora

En los días de transición del horario de verano, un día calendario tiene 23 horas o 25 horas. «Sumar 24 horas a la hora actual» y «dame la misma hora mañana» normalmente coinciden, pero en los días de transición difieren. Sumar 24 horas a la 1 AM en un día de adelanto produce las 2 AM del día siguiente, mientras que «la misma hora mañana» es la 1 AM.

La distinción tiene consecuencias reales para programaciones recurrentes («enviar correo a las 9 AM diariamente») y plazos («cancelar dentro de 24 horas»). Para «la misma hora de reloj cada día», suma un día calendario; para exactamente 24 horas de tiempo físico, suma 86400 segundos a la marca de tiempo UTC. Los diseños deben distinguir estas intenciones explícitamente en lugar de tratarlas como equivalentes.

Eventos recurrentes - El desafío de las aplicaciones de calendario

Una cita recurrente de «martes a las 14:00» debería permanecer a las 14:00 hora local a través de las transiciones del horario de verano. La intención del usuario es la hora de reloj local, no un momento UTC fijo. Por lo tanto, los eventos recurrentes deben almacenarse como un par (zona horaria, hora local), con el tiempo UTC real calculado dinámicamente para cada ocurrencia.

RFC 5545 (iCalendar) resuelve esto con DTSTART y RRULE. DTSTART especifica una hora local con zona horaria, y RRULE describe el patrón de repetición. El tiempo UTC de cada ocurrencia se calcula a partir de las reglas de la zona horaria incluyendo el horario de verano. Con este diseño, «14:00 local» permanece como 14:00 local a través de las transiciones, y evitas la vergonzosa queja de «mi reunión recurrente de los lunes a las 9 AM se movió a las 10 AM en marzo».

Almacenamiento en base de datos - TIMESTAMP vs TIMESTAMPTZ

El tipo TIMESTAMP (WITHOUT TIME ZONE) de PostgreSQL almacena valores textualmente sin ninguna conversión de zona horaria. TIMESTAMPTZ (WITH TIME ZONE) convierte las entradas a UTC para el almacenamiento y las reconvierte a la zona horaria de la sesión al leer. Para manejar correctamente el horario de verano, TIMESTAMPTZ es la opción por defecto correcta.

Si además necesitas recordar la hora local original tal como la expresó el usuario (por ejemplo, la hora de una cita reservada), TIMESTAMPTZ por sí solo pierde esa información en la conversión. El patrón consiste en almacenar TIMESTAMPTZ más el nombre de la zona horaria original en una columna separada, restaurando la intención del usuario en el momento de la presentación. Esto preserva tanto el momento absoluto como la intención específica de la zona del usuario.

Pruebas para el cambio horario - Capturar los errores bianuales

Los errores del horario de verano aparecen solo dos veces al año, por lo que pasan fácilmente las pruebas ordinarias. El código de prueba debe incluir explícitamente momentos alrededor de las transiciones: entrada de horas dentro del salto, resolución de horas duplicadas en el solapamiento, aritmética de duración a través de los días de transición y eventos recurrentes que atraviesan una transición. Sin estos casos específicos, el error aparece en producción.

Fijar la zona horaria del entorno de pruebas también es importante. Si los desarrolladores ejecutan en UTC+9 (sin cambio horario) pero producción se ejecuta en America/New_York (con cambio horario), las pruebas pasan localmente y fallan en producción. Pasa la zona horaria como parámetro a la función bajo prueba, o establece la variable de entorno TZ explícitamente durante las ejecuciones de prueba para eliminar la dependencia del entorno en los resultados.

XB!LINE

¿Te resultó útil este artículo?

Artículos Relacionados