2009-08-31 11 views
26

Qual è il modo corretto per convertire un'ora ingenua e una tzinfo in un'ora UTC? Dire che ho:conversione pytz utc

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

Primo modo, pytz ispirato:

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

Secondo modo, da 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) 

Inutile dire che questi due metodi producono risultati diversi per un bel po ' Fusi orari.

La domanda è: qual è la strada giusta?

+0

Sono stupito che nessuno cancellato 'Grazie' dal corpo della questione. Vediamo quanto ci vuole per rimuoverlo! – Art

+0

Secondo i miei calcoli, solo 897 giorni. – Will

+0

Grazie, Will, per correggere il torto! – Art

risposta

19

Il tuo primo metodo sembra essere approvato e dovrebbe essere compatibile con DST.

Si potrebbe accorciare un po 'piccolo, dal momento che pytz.utc = pytz.timezone ('UTC'), ma si sapeva che già :)

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

Perché normalizzare()? è davvero necessario? – kolypto

+1

@kolypto: Apparentemente 'tz.normalize()' terrà conto di Daylight Savings Time e altri fastidi che 'tz.localize()' non ha, come spiegato in altre risposte SO come [questo] (https: // stackoverflow .com/a/1379874/147 mila trecentoventi). – ewall

+2

@kolypto: alcuni orari locali non esistono, ad es., Quando l'orologio locale salta in avanti durante la transizione verso l'ora legale in alcuni paesi (emisfero settentrionale). 'tz.localize()' rispetta l'oggetto 'd' dato (non cambia il tempo, cerca solo di aggiungere un oggetto tzinfo appropriato) perciò' tz.normalize() 'è necessario per regolare i tempi non esistenti. Sebbene entrambe le volte (prima/dopo la regolazione) debbano corrispondere allo stesso tempo UTC, ad esempio, 'tz.normalize()' potrebbe non essere necessario se tutto ciò che facciamo è convertire il tempo in UTC come in questo caso. – jfs

0

Utilizzare il primo metodo. Non c'è motivo di reinventare la ruota della conversione del fuso orario

3

Qual è il modo giusto per convertire un tempo ingenuo e un tzinfo in un tempo 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

non è corretto. Se 'USE_TZ = True' allora' timezone.now() 'restituisce un datetime consapevole in UTC e quindi non dovresti chiamare' tz.normalize() 'su di esso. Se 'USE_TZ = False', django utilizza il fuso orario predefinito che potrebbe essere diverso da America/Los_Angeles e il codice è sbagliato anche in questo caso. – jfs

Problemi correlati