Ir al contenido principal
Tecnología

Conversión UTC en programación - Los patrones correctos para zonas horarias

Almacenar en UTC, mostrar en hora local

La regla más importante en el manejo de marcas de tiempo es: almacenar todo en UTC y convertir a hora local solo al mostrar datos al usuario. Los sistemas que violan esta regla producen errores sutiles en los cambios de horario de verano, y fallan completamente cuando se expanden a una segunda zona horaria. Todo equipo termina reaprendiendo esta lección, a menudo tras un incidente en producción.

UTC no tiene horario de verano y es monótonamente creciente, que es exactamente lo que se necesita para datos almacenados. Guardar en hora local crea el problema de «las dos 1:30 AM» en las transiciones de otoño: en Nueva York, la hora de reloj 1:30 AM ocurre una vez como EDT (UTC-4) y otra como EST (UTC-5), y un valor almacenado de 1:30 AM no puede indicar cuál fue. UTC evita esto por completo al representar el instante, no la lectura del reloj.

ISO 8601 - El formato de texto que realmente indica la zona horaria

Cuando las marcas de tiempo deben serializarse como texto, usa ISO 8601 (por ejemplo, 2026-05-15T07:00:00Z). La Z final significa UTC, mientras que desfases explícitos como +09:00 indican una zona local específica. La parte crucial es incluir información de zona horaria. Un simple 2026-05-15T16:00:00 sin desfase es ambiguo y provocará suposiciones de zona horaria en cualquier consumidor que lo analice.

Para el almacenamiento en bases de datos, TIMESTAMP WITH TIME ZONE (timestamptz) de PostgreSQL es la opción más limpia; internamente siempre almacena UTC y convierte a la zona de la sesión al leer. El tipo TIMESTAMP de MySQL también almacena en UTC internamente. Las columnas TIMESTAMP WITHOUT TIME ZONE requieren que la aplicación imponga la convención UTC solo por disciplina, lo cual inevitablemente falla cuando los equipos cambian o se añade código nuevo.

Patrones en JavaScript y TypeScript

El objeto Date de JavaScript representa internamente un valor de milisegundos-desde-la-época en UTC. Métodos como toString() y toLocaleString() muestran en la zona horaria local del entorno, que se establece por el navegador o por la variable de entorno TZ en Node.js. Para aplicaciones de servidor, establecer TZ=UTC en producción elimina las conjeturas en las marcas de los registros y hace que el comportamiento del servidor sea idéntico sin importar la ubicación del host.

Usa Intl.DateTimeFormat con la opción timeZone para formatear en zonas arbitrarias. Especificar un nombre IANA como America/New_York maneja automáticamente las transiciones de horario de verano. Calcular manualmente las diferencias de desfase es imprudente porque las reglas del horario de verano cambian con frecuencia; confiar en la base de datos IANA incluida en el sistema operativo o en el runtime es el único enfoque sostenible.

Los errores de zona horaria más comunes

El error más común es el mal manejo de campos de solo fecha. Almacenar un cumpleaños como 1990-03-15 y analizarlo con new Date('1990-03-15') hace que algunos navegadores lo interpreten como medianoche UTC, mostrando el 14 de marzo a un usuario en UTC-5. Los datos de solo fecha deberían incluir un componente horario de mediodía UTC (T12:00:00Z) para evitar cruces de frontera, o permanecer como cadena hasta el momento de formatear.

Un segundo error muy frecuente es configurar tareas cron en hora local. En la transición de primavera del horario de verano, las tareas programadas para las 2:30 AM se saltan porque las 2:30 no existen ese día. En la transición de otoño, las tareas de la 1:30 AM se ejecutan dos veces. Definir las programaciones en UTC y registrar las marcas en UTC elimina todo el problema, incluso al coste de una conversión mental ocasional al leer los registros.

Estrategia de pruebas para código de zonas horarias

Las pruebas para código de zonas horarias deben cubrir como mínimo: UTC+0 (Londres en invierno), desfase positivo (Tokio UTC+9), desfase negativo (Nueva York UTC-5), desfase de 30 minutos (India UTC+5:30), fronteras de transición de horario de verano, cruces de la línea internacional de fecha y cambios de año al final de diciembre. Cada uno de estos puede romper de forma independiente código que parece correcto en pruebas informales.

Presta atención también a la zona horaria del entorno de CI. Si los desarrolladores trabajan en UTC+9 localmente y CI se ejecuta en UTC, las pruebas pueden pasar localmente y fallar en CI sin causa obvia. El enfoque robusto es hacer que las funciones probadas reciban la zona horaria como parámetro (o congelarla mediante una constante en las pruebas), eliminando la dependencia del entorno de ejecución. Las pruebas basadas en propiedades con bibliotecas como fast-check o hypothesis pueden generar los casos límite que de otro modo pasarías por alto.

XB!LINE

¿Te resultó útil este artículo?

Artículos Relacionados