Introducción
El Horario de Verano (DST) es uno de los aspectos más complicados del manejo de fechas y horas. Este tutorial te enseñará cómo manejar correctamente las transiciones DST en tu código.
Lo que Aprenderás
- ✅ Qué es DST y cuándo ocurre
- ✅ El problema de "Spring Forward" (hora faltante)
- ✅ El problema de "Fall Back" (hora duplicada)
- ✅ Mejores prácticas para manejar DST
- ✅ Ejemplos prácticos en JavaScript y Python
¿Qué es DST?
El Horario de Verano es la práctica de adelantar los relojes durante los meses más cálidos:
- Spring Forward (Primavera): Los relojes avanzan 1 hora (ej. 2:00 AM → 3:00 AM)
- Fall Back (Otoño): Los relojes retroceden 1 hora (ej. 2:00 AM → 1:00 AM)
Fechas de Transición (2024)
| Región | Spring Forward | Fall Back |
|---|---|---|
| EE.UU. | 10 marzo | 3 noviembre |
| Europa | 31 marzo | 27 octubre |
| Australia | 6 octubre | 7 abril |
El Problema de la Hora Faltante
Cuando los relojes "saltan hacia adelante", una hora completa no existe.
JavaScript
JAVASCRIPT1// En zona horaria de España (Europe/Madrid) 2// El 31 de marzo de 2024, 2:00 AM no existe 3 4const fechaProblema = new Date('2024-03-31T02:30:00'); 5// JavaScript ajusta automáticamente a 3:30 AM 6 7// Usando Luxon para mejor control 8import { DateTime } from 'luxon'; 9 10const dt = DateTime.fromObject( 11 { year: 2024, month: 3, day: 31, hour: 2, minute: 30 }, 12 { zone: 'Europe/Madrid' } 13); 14console.log(dt.isValid); // true, pero ajustado 15console.log(dt.hour); // 3 (ajustado)
Python
PYTHON1from datetime import datetime 2from zoneinfo import ZoneInfo 3 4madrid = ZoneInfo('Europe/Madrid') 5 6# Esto se ajusta automáticamente 7dt = datetime(2024, 3, 31, 2, 30, tzinfo=madrid) 8print(dt) # Se ajusta a hora válida
El Problema de la Hora Duplicada
Cuando los relojes "retroceden", la misma hora ocurre dos veces.
JavaScript con Luxon
JAVASCRIPT1import { DateTime } from 'luxon'; 2 3// 27 de octubre 2024, 2:30 AM ocurre DOS veces en Madrid 4const primeraVez = DateTime.fromObject( 5 { year: 2024, month: 10, day: 27, hour: 2, minute: 30 }, 6 { zone: 'Europe/Madrid' } 7).set({ offset: 120 }); // +02:00 (antes del cambio) 8 9const segundaVez = DateTime.fromObject( 10 { year: 2024, month: 10, day: 27, hour: 2, minute: 30 }, 11 { zone: 'Europe/Madrid' } 12).set({ offset: 60 }); // +01:00 (después del cambio) 13 14console.log(primeraVez.toISO()); // 2024-10-27T02:30:00+02:00 15console.log(segundaVez.toISO()); // 2024-10-27T02:30:00+01:00
Python
PYTHON1from datetime import datetime 2from zoneinfo import ZoneInfo 3 4madrid = ZoneInfo('Europe/Madrid') 5 6# fold=0 significa primera ocurrencia (antes del cambio) 7# fold=1 significa segunda ocurrencia (después del cambio) 8primera = datetime(2024, 10, 27, 2, 30, fold=0, tzinfo=madrid) 9segunda = datetime(2024, 10, 27, 2, 30, fold=1, tzinfo=madrid) 10 11print(f"Primera: {primera} (offset: {primera.strftime('%z')})") 12print(f"Segunda: {segunda} (offset: {segunda.strftime('%z')})")
Mejores Prácticas
1. Siempre Trabaja en UTC
JAVASCRIPT1// ✅ Almacenar en UTC 2const timestampUtc = Date.now(); 3const fechaUtc = new Date(timestampUtc).toISOString(); 4// "2024-03-31T01:30:00.000Z" - siempre válido 5 6// Convertir a local solo para mostrar 7const local = new Date(timestampUtc).toLocaleString('es-ES', { 8 timeZone: 'Europe/Madrid' 9});
2. Usa Bibliotecas de Zona Horaria
PYTHON1# ✅ Usar zoneinfo o pytz 2from zoneinfo import ZoneInfo 3 4# ❌ No hacer cálculos manuales de offset 5offset = -5 # ¡Ignora DST!
3. Valida Fechas Durante Transiciones
JAVASCRIPT1function esFechaValida(year, month, day, hour, minute, zona) { 2 const dt = DateTime.fromObject( 3 { year, month, day, hour, minute }, 4 { zone: zona } 5 ); 6 7 if (!dt.isValid) { 8 return { valida: false, razon: 'Hora no existe (DST gap)' }; 9 } 10 11 // Verificar si la hora fue ajustada 12 if (dt.hour !== hour || dt.minute !== minute) { 13 return { 14 valida: true, 15 ajustada: true, 16 horaOriginal: `${hour}:${minute}`, 17 horaAjustada: `${dt.hour}:${dt.minute}` 18 }; 19 } 20 21 return { valida: true, ajustada: false }; 22}
4. Prueba con Fechas de Transición
PYTHON1# Incluye estas fechas en tus tests 2FECHAS_DST_TEST = [ 3 # Spring Forward (hora faltante) 4 datetime(2024, 3, 31, 2, 30), 5 6 # Fall Back (hora duplicada) 7 datetime(2024, 10, 27, 2, 30), 8 9 # Día normal 10 datetime(2024, 6, 15, 12, 0), 11]
Errores Comunes a Evitar
1. Asumir que todos los días tienen 24 horas
PYTHON1# ❌ Incorrecto 2siguiente_dia = fecha + timedelta(hours=24) 3 4# ✅ Correcto - usar días 5siguiente_dia = fecha + timedelta(days=1)
2. Codificar offsets manualmente
JAVASCRIPT1// ❌ Incorrecto 2const offset = -5 * 60 * 60 * 1000; // EST siempre 3 4// ✅ Correcto - usar biblioteca 5const zona = 'America/New_York'; // Maneja DST automáticamente
3. Ignorar ambigüedad en hora duplicada
PYTHON1# ❌ No especificar fold 2dt = datetime(2024, 10, 27, 2, 30, tzinfo=madrid) 3 4# ✅ Especificar fold explícitamente 5dt = datetime(2024, 10, 27, 2, 30, fold=1, tzinfo=madrid)
Resumen
- Spring Forward: Una hora no existe - valida y ajusta
- Fall Back: Una hora ocurre dos veces - especifica cuál
- Regla de oro: Almacena en UTC, muestra en local
- Usa bibliotecas: No calcules offsets manualmente
¡Prueba nuestro Convertidor de Zona Horaria para ver cómo funcionan las conversiones durante transiciones DST!