2009-08-31 17 views
26

¿Cuál es la forma correcta de convertir un tiempo ingenuo y un tzinfo en una hora UTC? Decir que tengo:conversión de pytz utc

d = datetime(2009, 8, 31, 22, 30, 30) 
tz = timezone('US/Pacific') 

Primera forma, pytz inspirado:

d_tz = tz.normalize(tz.localize(d)) 
utc = pytz.timezone('UTC') 
d_utc = d_tz.astimezone(utc) 

segundo camino, desde UTCDateTimeField

def utc_from_localtime(dt, tz): 
    dt = dt.replace(tzinfo=tz) 
    _dt = tz.normalize(dt) 
    if dt.tzinfo != _dt.tzinfo: 
     # Houston, we have a problem... 
     # find out which one has a dst offset 
     if _dt.tzinfo.dst(_dt): 
      _dt -= _dt.tzinfo.dst(_dt) 
     else: 
      _dt += dt.tzinfo.dst(dt) 
    return _dt.astimezone(pytz.utc) 

Ni que decir esas dos métodos producen resultados diferentes para unos pocos zonas horarias.

La pregunta es: ¿cuál es la forma correcta?

+0

me sorprende que nadie borra 'Gracias' del cuerpo de la cuestión. ¡Veamos cuánto tiempo lleva quitarlo! – Art

+0

Según mis cálculos, solo 897 días. – Will

+0

¡Gracias, Will, por enmendar el error! – Art

Respuesta

19

Su primer método parece ser el aprobado, y debe ser compatible con DST.

Usted puede acortarlo un poco pequeña, ya que pytz.utc = pytz.timezone ('UTC'), pero sabía que ya :)

tz = timezone('US/Pacific') 
def toUTC(d): 
    return tz.normalize(tz.localize(d)).astimezone(pytz.utc) 

print "Test: ", datetime.datetime.utcnow(), " = ", toUTC(datetime.datetime.now()) 
+0

¿Por qué normalize()? es realmente necesario? – kolypto

+1

@kolypto: Aparentemente 'tz.normalize()' tendrá en cuenta el horario de verano y otras molestias que 'tz.localize()' no contenga, como se explica en otras respuestas de SO como [este] (https: // stackoverflow .com/a/1379874/147320). – ewall

+2

@kolypto: algunas horas locales no existen, por ejemplo, cuando el reloj local salta hacia adelante en primavera durante la transición al horario de verano en algunos países (hemisferio norte). 'tz.localize()' respeta el objeto 'd' dado (no cambia la hora, solo intenta agregar un objeto tzinfo apropiado) por lo tanto' tz.normalize() 'es necesario para ajustar los tiempos no existentes. Aunque las dos veces (antes/después del ajuste) deben corresponder a la misma hora UTC, es decir, 'tz.normalize()' puede ser innecesario si todo lo que hacemos es convertir el tiempo a UTC como en este caso. – jfs

0

Utilice el primer método. No hay ninguna razón para reinventar la rueda de conversión de zona horaria

3

¿Cuál es la manera correcta de convertir un tiempo ingenuo y un tzinfo en un tiempo utc?

This answer enumerates some issues with converting a local time to UTC:

from datetime import datetime 
import pytz # $ pip install pytz 

d = datetime(2009, 8, 31, 22, 30, 30) 
tz = pytz.timezone('US/Pacific') 

# a) raise exception for non-existent or ambiguous times 
aware_d = tz.localize(d, is_dst=None) 
## b) assume standard time, adjust non-existent times 
#aware_d = tz.normalize(tz.localize(d, is_dst=False)) 
## c) assume DST is in effect, adjust non-existent times 
#aware_d = tz.normalize(tz.localize(naive_d, is_dst=True)) 

# convert to UTC 
utc_d = aware_d.astimezone(pytz.utc) 
-2
import pytz 
    from django.utils import timezone 

    tz = pytz.timezone('America/Los_Angeles') 
    time = tz.normalize(timezone.now()) 
+0

es incorrecta. Si 'USE_TZ = True',' timezone.now() 'devuelve un datetime al tanto en UTC y por lo tanto no debe llamar' tz.normalize() 'en él. Si 'USE_TZ = False', django usa la zona horaria predeterminada que puede ser diferente de America/Los_Angeles y el código también es incorrecto en este caso. – jfs

Cuestiones relacionadas