versiones guia español descargar actualizar python datetime timezone

python - guia - qgis manual



Cómo hacer que una zona horaria desconocida de datetime sea compatible con python (9)

Dos métodos que conozco puramente

from datetime import datetime import pytz naive = datetime.now() aware = naive.replace(tzinfo=pytz.UTC)

o

aware = pytz.UTC.localize(naive)

por supuesto, puedes usar cualquier zona horaria en lugar de UTC,

Lo que necesito hacer

Tengo un objeto de fecha y hora que no conoce la zona horaria, al que debo agregar una zona horaria para poder compararlo con otros objetos de fecha y hora que tienen en cuenta la zona horaria. No quiero convertir mi aplicación completa a la zona horaria sin saberlo para este caso heredado.

Lo que he intentado

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 muy sorprendente que esto haya fallado, ya que en realidad está tratando de hacer una conversión. Reemplazar pareció ser 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 configurar el tzinfo, pero no hace que el objeto sea consciente. Me estoy preparando para volver a manipular 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 tanto en python 2.6 como en python 2.7, con los mismos resultados.

Contexto

Estoy escribiendo un analizador para algunos archivos de datos. Hay un formato antiguo que debo admitir donde la cadena de fecha no tiene un indicador de zona horaria. Ya he arreglado la fuente de datos, pero aún necesito admitir el formato de datos heredado. Una conversión de una sola vez de los datos heredados no es una opción por varias razones comerciales de BS. Aunque en general, no me gusta la idea de codificar correctamente una zona horaria predeterminada, en este caso parece ser la mejor opción. Sé con una confianza razonable que todos los datos heredados en cuestión están en UTC, por lo que estoy preparado para aceptar el riesgo de no cumplir con los mismos en este caso.


En el formato de la respuesta de unutbu; Hice un módulo de utilidad que maneja cosas como esta, con una sintaxis más intuitiva. Se puede instalar con pip.

import datetime import saturn unaware = datetime.datetime(2011, 8, 15, 8, 15, 12, 0) now_aware = saturn.fix_naive(unaware) now_aware_madrid = saturn.fix_naive(unaware, ''Europe/Madrid'')


En general, para hacer que una zona horaria sin fecha de inicio tenga en cuenta, use el método de localización :

import datetime import pytz unaware = datetime.datetime(2011, 8, 15, 8, 15, 12, 0) aware = datetime.datetime(2011, 8, 15, 8, 15, 12, 0, pytz.UTC) now_aware = pytz.utc.localize(unaware) assert aware == now_aware

Para la zona horaria UTC, no es realmente necesario usar la localize ya que no hay un cálculo de horario de verano para manejar:

now_aware = unaware.replace(tzinfo=pytz.UTC)

trabajos. ( .replace devuelve un nuevo datetime; no se modifica unaware ).


Esto codifica las answers @ Sérgio y @ unutbu. Solo "funcionará" con un objeto pytz.timezone o una cadena de zona horaria de la IANA .

def make_tz_aware(dt, tz=''UTC'', is_dst=None): """Add timezone information to a datetime object, only if it is naive.""" tz = dt.tzinfo or tz try: tz = pytz.timezone(tz) except AttributeError: pass return tz.localize(dt, is_dst=is_dst)

Esto parece lo que debe hacer datetime.localize() (o .inform() o .awarify() ), aceptar tanto cadenas como objetos de zona horaria para el argumento tz y valor predeterminado a UTC si no se especifica una zona horaria.


Estoy de acuerdo con las respuestas anteriores, y está bien si está bien para comenzar en UTC. Pero creo que también es un escenario común para que las personas trabajen con un valor que tenga en cuenta tz que tenga una fecha y hora que tenga una zona horaria local no UTC.

Si solo tuviera que ir por su nombre, probablemente se deduciría que replace () será aplicable y producirá el objeto adecuado para la fecha y hora. Este no es el caso.

El reemplazo (tzinfo = ...) parece ser aleatorio en su comportamiento . Por eso es inútil. ¡No uses esto!

Localizar es la función correcta a utilizar. Ejemplo:

localdatetime_aware = tz.localize(datetime_nonaware)

O un ejemplo más completo:

import pytz from datetime import datetime pytz.timezone(''Australia/Melbourne'').localize(datetime.now())

me da un valor de fecha y hora de la hora local actual:

datetime.datetime(2017, 11, 3, 7, 44, 51, 908574, tzinfo=<DstTzInfo ''Australia/Melbourne'' AEDT+11:00:00 DST>)


Para agregar zona horaria local; (usando dateutil)

from dateutil import tz import datetime dt_unaware = datetime.datetime(2017, 6, 24, 12, 24, 36) dt_aware = dt_unaware.replace(tzinfo=tz.tzlocal())


Todos estos ejemplos usan un módulo externo, pero puede lograr el mismo resultado usando solo el módulo datetime, como también se presenta en esta respuesta SO :

from datetime import datetime from datetime import timezone dt = datetime.now() dt.replace(tzinfo=timezone.utc) print(dt.replace(tzinfo=timezone.utc).isoformat()) ''2017-01-12T22:11:31+00:00''

Menos dependencias y sin problemas de pytz.

NOTA: Si desea usar esto con python3 y python2, también puede usarlo para la importación de la zona horaria (codificada para UTC):

try: from datetime import timezone utc = timezone.utc except ImportError: #Hi there python2 user class UTC(tzinfo): def utcoffset(self, dt): return timedelta(0) def tzname(self, dt): return "UTC" def dst(self, dt): return timedelta(0) utc = UTC()


Tuve uso de dt_aware a dt_unware

dt_unaware = dt_aware.replace(tzinfo=None)

y dt_unware a dt_aware

from pytz import timezone localtz = timezone(''Europe/Lisbon'') dt_aware = localtz.localize(dt_unware)

Pero responder antes también es una buena solución.


Utilizo esta declaración en Django para convertir un tiempo inconsciente en un consciente:

from django.utils import timezone dt_aware = timezone.make_aware(dt_unaware, timezone.get_current_timezone())