Pytz localize vs datetime replace

Estoy teniendo algunos problemas extraños con la función .localize () de pytz. A veces no haría ajustes a la fecha y hora localizada:

.localize comportamiento:

>>> tz  >>> d datetime.datetime(2009, 9, 2, 14, 45, 42, 91421) >>> tz.localize(d) datetime.datetime(2009, 9, 2, 14, 45, 42, 91421, tzinfo=) >>> tz.normalize(tz.localize(d)) datetime.datetime(2009, 9, 2, 14, 45, 42, 91421, tzinfo=) 

Como puede ver, el tiempo no se ha modificado como resultado de las operaciones de localización / normalización. Sin embargo, si se usa .replace:

 >>> d.replace(tzinfo=tz) datetime.datetime(2009, 9, 2, 14, 45, 42, 91421, tzinfo=) >>> tz.normalize(d.replace(tzinfo=tz)) datetime.datetime(2009, 9, 2, 15, 1, 42, 91421, tzinfo=) 

Lo que parece hacer ajustes en fecha y hora.

La pregunta es: ¿cuál es la correcta y por qué otros están mal?

localize solo asume que la fecha y hora ingenua que usted pasa es “correcta” (¡excepto para no saber acerca de la zona horaria!) y por lo tanto solo establece la zona horaria, no hay otros ajustes.

Puede (y es recomendable …) trabajar internamente en UTC (en lugar de con tiempos de datos ingenuos) y usar replace cuando necesite realizar E / S de tiempos de datos de forma localizada ( normalize manejará el DST y similares).

localize es la función correcta que se debe utilizar para crear objetos de fecha y hora con un valor inicial fijo de fecha y hora. El objeto resultante de fecha y hora tendrá el valor original de fecha y hora. Un patrón de uso muy común desde mi punto de vista, y uno que quizás Pytz pueda documentar mejor.

replace(tzinfo = ...) desafortunadamente se llama. Es una función que es aleatoria en su comportamiento. Recomendaría evitar el uso de esta función para establecer zonas horarias a menos que disfrute del dolor autoinfligido. Ya he sufrido bastante con el uso de esta función.

Me doy cuenta de que estoy un poco atrasado en esto … pero esto es lo que encontré para funcionar bien. Trabaja en UTC como Alex dijo:

 tz = pytz.timezone('Africa/Abidjan') now = datetime.datetime.utcnow() 

Luego para localizar:

 tzoffset = tz.utcoffset(now) mynow = now+tzoffset 

Y este método maneja DST perfectamente

Esta clase DstTzInfo se usa para las zonas horarias donde el desplazamiento de UTC cambia en ciertos puntos en el tiempo. Por ejemplo (como probablemente sepa), muchas ubicaciones hacen la transición al “horario de verano” al comienzo del verano y luego vuelven a la “hora estándar” al final del verano. Cada instancia de DstTzInfo solo representa una de estas zonas horarias, pero los métodos de “localización” y “normalización” lo ayudan a obtener la instancia correcta.

Para Abidjan, solo ha habido una transición (según pytz), y eso fue en 1912:

 >>> tz = pytz.timezone('Africa/Abidjan') >>> tz._utc_transition_times [datetime.datetime(1, 1, 1, 0, 0), datetime.datetime(1912, 1, 1, 0, 16, 8)] 

El objeto tz que obtenemos de pytz representa la zona horaria anterior a 1912:

 >>> tz  

Ahora, mirando sus dos ejemplos, vea que cuando llama a tz.localize (d) NO obtiene esta zona horaria anterior a 1912 agregada a su objeto de fecha y hora original. Supone que el objeto de fecha y hora que le da representa la hora local en la zona horaria correcta para esa hora local , que es la zona horaria posterior a 1912.

Sin embargo, en su segundo ejemplo, utilizando d.replace (tzinfo = tz), su objeto datetime representa el tiempo en la zona horaria anterior a 1912. Probablemente esto no sea lo que quisiste decir. Luego, cuando llama a dt.normalize, esto se convierte en la zona horaria correcta para ese valor de fecha y hora, es decir, la zona horaria posterior a 1912.