datetime con zona horaria pytz. Diferente desplazamiento dependiendo de cómo se configura tzinfo

Me encontré con una situación interesante hoy. ¿Alguien puede explicar por qué las compensaciones para ts1 y ts2 son diferentes? ts1 es un objeto de fecha y hora que es consciente de la zona horaria desde el principio. ts2 es un objeto de fecha y hora que comienza en un huso horario y tiene su tzinfo reemplazado. Sin embargo, terminan con diferentes compensaciones.

>>> from pytz import timezone >>> EST = timezone('America/New_York') >>> ts1 = datetime.datetime.now(tz=EST) >>> ts2 = datetime.datetime.now() >>> ts2 = ts2.replace(tzinfo=EST) >>> print ts1 2014-05-16 11:25:16.749748-04:00 >>> print ts2 2014-05-16 11:25:19.581710-05:00 

Cuando llama a ts2.replace(tzinfo=EST) , el objeto tzinfo que está obteniendo no coincide con el que obtiene con ts1 :

 >>> ts1 datetime.datetime(2014, 5, 16, 11, 51, 7, 916090, tzinfo=) >>> ts2 datetime.datetime(2014, 5, 16, 11, 51, 30, 922692, tzinfo=) 

Terminas con LMT en lugar de EDT.

La documentación de pytz realidad señala que el uso de pytz con el argumento tzinfo de los objetos de fecha y hora estándar simplemente no funciona para muchas zonas horarias:

Desafortunadamente, el uso del argumento tzinfo de los constructores de fecha y hora estándar ” no funciona ” con pytz para muchas zonas horarias.

>>> datetime(2002, 10, 27, 12, 0, 0, tzinfo=amsterdam).strftime(fmt) '2002-10-27 12:00:00 LMT+0020'

Sin embargo, es seguro para las zonas horarias sin transiciones de horario de verano, como UTC:

>>> datetime(2002, 10, 27, 12, 0, 0, tzinfo=pytz.utc).strftime(fmt) '2002-10-27 12:00:00 UTC+0000'

No estoy exactamente seguro de por qué el primero funciona; quizás porque en realidad no tiene que convertir nada cuando el objeto se construye inicialmente con el objeto tzinfo .

Editar :

Ah, la documentación de Python señala que el uso de datetime.datetime.now() con el tz es equivalente a:

 EST.fromutc(datetime.utcnow().replace(tzinfo=EST)) 

Lo que significa que estás convirtiendo desde UTC, que es seguro con pytz . Por eso es que la primera funciona.

De acuerdo con la documentación , la forma correcta de aplicar una zona horaria a una fecha y hora ingenuas es con el método de localize .

 ts1 = eastern.localize(datetime.datetime.now()) 

Además, le recomiendo que evite usar EST como un nombre de variable, ya que suele ser estándar para “Hora estándar del este”, y America/New_York incluye tanto la “Hora estándar del este” (EST) como la “Hora de verano del Este” (EDT).