Lo que necesito hacer
Tengo un objeto datetime que no conoce la zona horaria, al que necesito agregar una zona horaria para poder compararlo con otros objetos datetime que reconocen la zona horaria. No quiero convertir toda mi aplicación a la zona horaria sin saberlo para este caso heredado.
Lo que he probado
Primero, para demostrar el problema:
Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import datetime
>>> import pytz
>>> unaware = datetime.datetime(2011,8,15,8,15,12,0)
>>> unaware
datetime.datetime(2011, 8, 15, 8, 15, 12)
>>> aware = datetime.datetime(2011,8,15,8,15,12,0,pytz.UTC)
>>> aware
datetime.datetime(2011, 8, 15, 8, 15, 12, tzinfo=<UTC>)
>>> aware == unaware
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't compare offset-naive and offset-aware datetimes
Primero, probé astimezone:
>>> unaware.astimezone(pytz.UTC)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: astimezone() cannot be applied to a naive datetime
>>>
No es terriblemente sorprendente que esto haya fallado, ya que en realidad está tratando de hacer una conversión. Reemplazar parecía una mejor opción (según Python: ¿Cómo obtener un valor de datetime.today () que sea "consciente de la zona horaria"? ):
>>> unaware.replace(tzinfo=pytz.UTC)
datetime.datetime(2011, 8, 15, 8, 15, 12, tzinfo=<UTC>)
>>> unaware == aware
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't compare offset-naive and offset-aware datetimes
>>>
Pero como puede ver, reemplazar parece establecer el tzinfo, pero no hace que el objeto sea consciente. Me estoy preparando para volver a tratar la cadena de entrada para tener una zona horaria antes de analizarla (estoy usando dateutil para analizar, si eso importa), pero eso parece increíblemente torpe.
Además, he intentado esto en python 2.6 y python 2.7, con los mismos resultados.
Contexto
Estoy escribiendo un analizador para algunos archivos de datos. Hay un formato antiguo que necesito admitir donde la cadena de fecha no tiene un indicador de zona horaria. Ya arreglé la fuente de datos, pero aún necesito admitir el formato de datos heredado. Una conversión única de los datos heredados no es una opción por varias razones comerciales de BS. Si bien, en general, no me gusta la idea de codificar una zona horaria predeterminada, en este caso parece la mejor opción. Sé con bastante confianza que todos los datos heredados en cuestión están en UTC, por lo que estoy dispuesto a aceptar el riesgo de incumplimiento en ese caso.
unaware.replace()
volveríaNone
si estuviera modificando elunaware
objeto en el lugar. El REPL muestra que.replace()
devuelve un nuevodatetime
objeto aquí.import datetime; datetime.datetime.now(datetime.timezone.utc)
tz
para ser más legible:datetime.datetime.now(tz=datetime.timezone.utc)
Respuestas:
En general, para que una zona horaria de fecha y hora ingenua sea consciente, use el método de localización :
Para la zona horaria UTC, no es realmente necesario usarlo
localize
ya que no hay un cálculo del horario de verano para manejar:trabajos. (
.replace
devuelve una nueva fecha y hora; no se modificaunaware
)fuente
aware = datetime(..., tz)
use.localize()
en su lugar.tz.localize(..., is_dst=None)
afirma que no lo es.Todos estos ejemplos usan un módulo externo, pero puede lograr el mismo resultado usando solo el módulo de fecha y hora, como también se presenta en esta respuesta SO :
Menos dependencias y sin problemas de pytz.
NOTA: Si desea usar esto con python3 y python2, puede usar esto también para la importación de la zona horaria (codificada para UTC):
fuente
pytz
problemas, ¡me alegro de haberme desplazado un poco hacia abajo! No quería abordar conpytz
mis servidores remotos de hecho :)from datetime import timezone
en cuenta que funciona en py3 pero no en py2.7.dt.replace(tzinfo=timezone.utc)
devuelve una nueva fecha y hora, no se modificadt
en su lugar. (Editaré para mostrar esto).tz = pytz.timezone('America/Chicago')
Tuve uso de dt_aware a dt_unaware
y dt_unware a dt_aware
pero responder antes también es una buena solución.
fuente
localtz.localize(dt_unware, is_dst=None)
para generar una excepción sidt_unware
representa la hora local no existente o ambigua (nota: no hubo tal problema en la revisión anterior de su respuesta dondelocaltz
estaba UTC porque UTC no tiene transiciones DSTUtilizo esta declaración en Django para convertir un tiempo inconsciente en consciente:
fuente
Estoy de acuerdo con las respuestas anteriores, y está bien si está de acuerdo en comenzar en UTC. Pero creo que también es un escenario común para las personas trabajar con un valor consciente de tz que tiene una fecha y hora que tiene una zona horaria local no UTC.
Si solo fuera por su nombre, uno probablemente inferiría que replace () será aplicable y producirá el objeto adecuado de fecha y hora. Este no es el caso.
el reemplazo (tzinfo = ...) parece ser aleatorio en su comportamiento . Por lo tanto, es inútil. ¡No uses esto!
localizar es la función correcta para usar. Ejemplo:
O un ejemplo más completo:
me da un valor de fecha y hora consciente de la zona horaria de la hora local actual:
fuente
replace(tzinfo=...)
en una zona horaria que no sea UTC afectará su fecha y hora. Tengo en-07:53
lugar de-08:00
por ejemplo. Ver stackoverflow.com/a/13994611/1224827replace(tzinfo=...)
tener un comportamiento inesperado?Use
dateutil.tz.tzlocal()
para obtener la zona horaria en su uso dedatetime.datetime.now()
ydatetime.datetime.astimezone()
:Tenga en cuenta que
datetime.astimezone
primero convertirá sudatetime
objeto a UTC y luego a la zona horaria, que es lo mismo que llamardatetime.replace
con la información de la zona horaria originalNone
.fuente
.replace(tzinfo=dateutil.tz.UTC)
.replace(tzinfo=datetime.timezone.utc)
Esto codifica las respuestas de @ Sérgio y @ unutbu . "Funcionará" con un
pytz.timezone
objeto o una cadena de zona horaria de IANA .Esto parece lo
datetime.localize()
(o.inform()
o.awarify()
) debe hacer, aceptar ambas cadenas y objetos de zona horaria para el argumento tz y por defecto a la hora UTC, si no se especifica ninguna zona horaria.fuente
Python 3.9 agrega el
zoneinfo
módulo, por lo que ahora solo se necesita la biblioteca estándar.Adjunte una zona horaria:
Adjunte la zona horaria local del sistema:
Posteriormente se convierte correctamente a otras zonas horarias:
Lista de Wikipedia de zonas horarias disponibles
Windows no tiene una base de datos de zona horaria del sistema, por lo que aquí se necesita un paquete adicional:
Hay un backport para permitir su uso en Python 3.6 a 3.8 :
Entonces:
fuente
pip install tzdata
En el formato de la respuesta de unutbu; Creé un módulo de utilidad que maneja cosas como esta, con una sintaxis más intuitiva. Se puede instalar con pip.
fuente
para aquellos que solo quieren hacer una fecha y hora consciente de la zona horaria
fuente
bastante nuevo en Python y encontré el mismo problema. Encuentro esta solución bastante simple y para mí funciona bien (Python 3.6):
fuente
Cambiar entre zonas horarias
fuente