La zona horaria es un problema difícil. El horario de verano es un problema aún más difícil. Me encontré caminando en problemas y problemas cuando comencé a usar datetime en Python correctamente. Así que decido escribir un blog para compartir mi experiencia.

«Naive » y»Aware»

Lo primero que hay que saber es que en Python hay dos tipos de datetime: offset-naive y offset-aware. Offset naive significa que la fecha y hora no tiene información de zona horaria. Podría ser muy propenso a errores si es nuevo en Python. Si mezcla un datetime ingenuo y un datetime consciente, se producirá un error. Y Python no tiene soporte de zona horaria incorporado, necesita usar pytz, un módulo para información de zona horaria.

import pytz
from datetime import datetimetznaive_datetime = datetime(2018, 1, 1, 12, 0)
tzaware_datetime = datetime(2018, 1, 1, 12, 0, tzinfo=pytz.utc)# this will raise an error
tznaive_datetime == tzaware_datetime

Para evitar este tipo de problemas, tendrá que asegurarse de que sus objetos datetime sean siempre ingenuos en desplazamiento o siempre conscientes de desplazamiento. Pero no podemos evitar tratar con la zona horaria, así que mi mejor práctica es trabajar siempre con offset-consciente datetime.

El valor predeterminado de Python es datetime ingenuo. now() devuelve ingenuo datetime en su zona horaria local, y utcnow() también devuelve un ingenuo datetime, incluso la función ya indica la zona horaria UTC! Necesitará el módulo pytz y también el módulo tzlocal para hacer las cosas bien. A continuación se muestra cómo obtengo tiempo con la zona horaria correcta.

import datetime
import pytz
import tzlocaldef utcnow():
return pytz.utc.localize(datetime.utcnow())def now():
return tzlocal.get_localzone().localize(datetime.now())

Analizar la fecha y hora con zona horaria

Actualizar: Esto es solo un problema en Python 2

Otra sorpresa es que python strptime El analizador no funciona con zona horaria. El siguiente código simplemente fallará.

>>> from datetime import datetime
>>> datetime.strptime('2017-11-15T12:00:00-0700', '%Y-%m-%dT%H:%M:%S%z')ValueError: 'z' is a bad directive in format '%Y-%m-%dT%H:%m:%S%z'

Para analizar datetime con la zona horaria, necesitará otro módulo python-dateutil . Este módulo proporciona un analizador que funcionará con la zona horaria. Ahora usted puede analizar datetime con la zona horaria!

>>> from dateutil import parser
>>> parser.parse('2017-11-15T12:00:00-07')datetime.datetime(2017, 11, 15, 12, 0, tzinfo=tzoffset(None, -25200))

Timedelta y DST

Lo último que debe tener cuidado al manipular la fecha y hora con reconocimiento de desplazamiento. pytz le ayudará a saber si una fecha está bajo la influencia del horario de verano marcando el método dst().

>>> import pytz
>>> pst = pytz.timezone("US/Pacific")
>>> pst.localize(datetime(2017, 10, 1)).dst()
datetime.timedelta(0, 3600)
>>> pst.localize(datetime(2017, 12, 1)).dst()
datetime.timedelta(0)

Nota: El horario de verano de 2017 finalizó el 5 de noviembre. Por lo tanto, cualquier fecha posterior al 5 de noviembre tendrá timedelta(0)

, Pero la información dst() no se actualiza cuando manipula la fecha y hora

>>> (pst.localize(datetime(2017, 10, 1)) + timedelta(days=60)).dst()
datetime.timedelta(0, 3600)

Lo que realmente puede hacer es convertir de nuevo a la fecha y hora de desplazamiento naive,…

pst.localize(yourdate.replace(tzinfo=None) + td).dst()

Resumen

Trabajar con Datetime en Python es propenso a errores. Es porque Python no soporta bien la fecha y hora y la zona horaria. Tendrás que usar muchos módulos adicionales. Sin embargo, en realidad hay una bala de plata, solo puedes usar arrow. Este módulo proporciona un reemplazo para el módulo datetime de python, y siempre tiene en cuenta el desplazamiento, y también resuelve todos los problemas que menciono anteriormente. Lo único que puede preocuparme es la integración con otras aplicaciones externas como Spark.