446 votos

Cómo hacer una datetime zona horaria inconsciente consciente en python

Lo que tengo que hacer

Tengo una zona horaria que no reconocen objeto datetime, a la que tengo que agregar una zona de tiempo con el fin de poder compararlo con otros de la zona horaria-aware datetime objetos. No quiero convertir mi solicitud completa a la zona horaria conscientes de este legado caso.

Lo he Intentado

En primer lugar, 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

En primer lugar, traté de 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 tremendamente sorprendente en este error, ya que es en realidad tratando de hacer una conversión. Reemplazar parecía una mejor opción (como por Python: Cómo obtener un valor de datetime.hoy() que es la "zona horaria consciente"?):

>>> 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 se puede ver, reemplazar parece establecer el tzinfo, pero no hacer que el objeto de conocimiento. Me estoy preparando para volver a caer a cuidarse de la cadena de entrada para tener una zona horaria antes del análisis (estoy usando dateutil para analizar, si que importa), pero que parece ser increíblemente desacoplados.

También, he intentado esto en python de python 2.6 y 2.7, con los mismos resultados.

Contexto

Estoy escribiendo un analizador para algunos de los archivos de datos. Hay un viejo formato necesito para ayudar en la fecha de la cadena no tiene un indicador de zona horaria. Ya he corregido el origen de datos, pero aún me falta para apoyar el legado de formato de datos. Una vez la conversión de los datos de legado no es una opción para varias BS razones. Mientras que en general, no me gusta la idea de codificar una zona horaria por defecto, en este caso parece la mejor opción. Sé que con razonable confianza de que todos los datos heredados en cuestión es UTC, así que estoy dispuesto a aceptar el riesgo de impago a que, en este caso.

528voto

unutbu Puntos 222216

En general, para hacer una zona horaria consciente datetime ingenuo, utilice el método Localizar :

 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
 

Por la zona horaria UTC, no es realmente necesario utilizar localize ya que no hay cálculo del tiempo de ahorro de luz diurna a manejar:

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

funciona. ( .replace devuelve una nueva fecha y hora; no modifica unaware .)

76voto

Sérgio Puntos 854

Tuve que usar 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 la respuesta antes de que también es una buena solución.

9voto

hobs Puntos 3020

Para codificar la lógica discutido en las respuestas por @Sergio y @unutbu y agregar la característica "sólo el trabajo", ya sea con un pytz.timezone objeto o una IANA Zona horaria de la cadena.

def make_tz_aware(dt, tz='UTC'):
    """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) 

Esto es, básicamente, cómo me imagino a un datetime.localize() (o .inform() o .awarify()) método de trabajo, la aceptación de las cadenas y la zona horaria de los objetos para los tz argumento y el uso de UTC, si no se especifica una zona horaria.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X