Tutoriales
Trabajando con Zonas Horarias en Python: Tutorial Completo
Introducción
Manejar zonas horarias en Python puede ser complicado, pero es esencial para aplicaciones que trabajan con usuarios de todo el mundo. Este tutorial te guiará a través de las mejores prácticas para trabajar con zonas horarias en Python.
Lo que Aprenderás
- ✅ Diferencia entre datetime naive y aware
- ✅ Usar pytz para zonas horarias
- ✅ Usar zoneinfo (Python 3.9+)
- ✅ Convertir entre zonas horarias
- ✅ Manejar horario de verano (DST)
- ✅ Mejores prácticas y errores comunes
Prerrequisitos
- Python 3.6 o superior
- Conocimiento básico de datetime
Paso 1: Entender Naive vs Aware
Datetime Naive (Sin Zona Horaria)
from datetime import datetime
# Naive - sin información de zona horaria
dt_naive = datetime(2024, 1, 15, 12, 30, 0)
print(dt_naive.tzinfo) # None
Datetime Aware (Con Zona Horaria)
from datetime import datetime, timezone
# Aware - incluye zona horaria
dt_aware = datetime(2024, 1, 15, 12, 30, 0, tzinfo=timezone.utc)
print(dt_aware.tzinfo) # UTC
Regla de oro: Siempre trabaja con datetimes aware.
Paso 2: Trabajar con UTC
from datetime import datetime, timezone
# Hora actual en UTC
ahora_utc = datetime.now(timezone.utc)
print(ahora_utc)
# Salida: 2024-01-15 12:30:00+00:00
# Desde timestamp Unix
timestamp = 1705321800
dt = datetime.fromtimestamp(timestamp, tz=timezone.utc)
print(dt)
# Salida: 2024-01-15 12:30:00+00:00
Paso 3: Usar pytz
import pytz
from datetime import datetime
# Crear zona horaria
madrid = pytz.timezone('Europe/Madrid')
nueva_york = pytz.timezone('America/New_York')
# Hora actual en Madrid
ahora_madrid = datetime.now(madrid)
print(f"Madrid: {ahora_madrid}")
# Convertir UTC a Madrid
utc = pytz.UTC
ahora_utc = datetime.now(utc)
ahora_madrid = ahora_utc.astimezone(madrid)
print(f"Madrid desde UTC: {ahora_madrid}")
Advertencia con pytz
# ❌ INCORRECTO - no usar replace con pytz
dt = datetime(2024, 1, 15, 12, 0)
dt_mal = dt.replace(tzinfo=madrid) # ¡No funciona correctamente!
# ✅ CORRECTO - usar localize
dt = datetime(2024, 1, 15, 12, 0)
dt_bien = madrid.localize(dt)
Paso 4: Usar zoneinfo (Python 3.9+)
from datetime import datetime
from zoneinfo import ZoneInfo
# Crear zona horaria
madrid = ZoneInfo('Europe/Madrid')
tokio = ZoneInfo('Asia/Tokyo')
# Hora actual en Madrid
ahora_madrid = datetime.now(madrid)
print(ahora_madrid)
# Convertir entre zonas
ahora_tokio = ahora_madrid.astimezone(tokio)
print(ahora_tokio)
Paso 5: Convertir Entre Zonas Horarias
from datetime import datetime
from zoneinfo import ZoneInfo
# Crear datetime en una zona
madrid = ZoneInfo('Europe/Madrid')
nueva_york = ZoneInfo('America/New_York')
tokio = ZoneInfo('Asia/Tokyo')
dt_madrid = datetime(2024, 1, 15, 14, 30, tzinfo=madrid)
# Convertir a otras zonas
dt_ny = dt_madrid.astimezone(nueva_york)
dt_tokio = dt_madrid.astimezone(tokio)
print(f"Madrid: {dt_madrid}")
print(f"Nueva York: {dt_ny}")
print(f"Tokio: {dt_tokio}")
Paso 6: Manejar DST (Horario de Verano)
from datetime import datetime
from zoneinfo import ZoneInfo
madrid = ZoneInfo('Europe/Madrid')
# Invierno (CET, UTC+1)
invierno = datetime(2024, 1, 15, 12, 0, tzinfo=madrid)
print(f"Invierno: {invierno} (offset: {invierno.strftime('%z')})")
# Salida: 2024-01-15 12:00:00+01:00
# Verano (CEST, UTC+2)
verano = datetime(2024, 7, 15, 12, 0, tzinfo=madrid)
print(f"Verano: {verano} (offset: {verano.strftime('%z')})")
# Salida: 2024-07-15 12:00:00+02:00
Paso 7: Almacenar y Recuperar Timestamps
from datetime import datetime, timezone
from zoneinfo import ZoneInfo
# Siempre almacenar en UTC
def guardar_evento(dt_local, zona_usuario):
"""Convierte hora local a UTC para almacenar"""
if dt_local.tzinfo is None:
zona = ZoneInfo(zona_usuario)
dt_local = dt_local.replace(tzinfo=zona)
return dt_local.astimezone(timezone.utc)
# Mostrar en zona local del usuario
def mostrar_evento(dt_utc, zona_usuario):
"""Convierte UTC a hora local para mostrar"""
zona = ZoneInfo(zona_usuario)
return dt_utc.astimezone(zona)
# Ejemplo
hora_local = datetime(2024, 1, 15, 14, 30)
hora_utc = guardar_evento(hora_local, 'Europe/Madrid')
print(f"Almacenado: {hora_utc}")
hora_mostrar = mostrar_evento(hora_utc, 'America/New_York')
print(f"Mostrado en NY: {hora_mostrar}")
Errores Comunes a Evitar
1. Usar datetime.now() sin zona
# ❌ Incorrecto
ahora = datetime.now()
# ✅ Correcto
ahora = datetime.now(timezone.utc)
2. Comparar naive con aware
# ❌ Esto causa TypeError
naive = datetime(2024, 1, 15, 12, 0)
aware = datetime(2024, 1, 15, 12, 0, tzinfo=timezone.utc)
# naive < aware # TypeError!
# ✅ Convertir primero
naive_utc = naive.replace(tzinfo=timezone.utc)
# naive_utc < aware # Funciona
3. Ignorar DST en cálculos
from datetime import timedelta
from zoneinfo import ZoneInfo
# Durante cambio de DST, usar timedelta puede fallar
madrid = ZoneInfo('Europe/Madrid')
# ✅ Mejor: trabajar en UTC y luego convertir
Resumen
Has aprendido cómo:
- Diferenciar entre datetime naive y aware
- Usar pytz y zoneinfo para zonas horarias
- Convertir entre diferentes zonas horarias
- Manejar DST correctamente
- Almacenar siempre en UTC y mostrar en hora local
¡Prueba nuestro Convertidor de Zona Horaria para practicar conversiones!
Pruébalo
Prueba la conversión de timestamps
¿Necesitas más opciones? Convertidor de zona horaria