2015-08-07 18 views
9

delorean docs mostrare questo modo per ottenere l'ora corrente in un determinato fuso orariousing datetime:quando fallisce `datetime.now (pytz_timezone)`

from datetime import datetime 
from pytz import timezone 

EST = "US/Eastern" 
UTC = "UTC" 

d = datetime.utcnow() 
utc = timezone(UTC) 
est = timezone(EST) 
d = utc.localize(d) 
d = est.normalize(EST) 

e confrontarlo con il codice di Delorian-based:

from delorean import Delorean 

EST = "US/Eastern" 

d = Delorean(timezone=EST) 

I believe l'esempio datetime dovrebbe essere scritto come:

from datetime import datetime 
import pytz 

eastern_timezone = pytz.timezone("US/Eastern") 
d = datetime.now(eastern_timezone) 

che è più conciso.

Ci sono casi in cui l'ultimo esempio di codice fallisce mentre il primo continua a funzionare?


Aggiornamento:the current example:

from datetime import datetime 
import pytz 

d = datetime.utcnow() 
d = pytz.utc.localize(d) 

est = pytz.timezone('US/Eastern') 
d = est.normalize(d) 
return d 

che è ancora troppo prolisso.

Gli alambicchi domanda sorge: do you need the explicit round-trip via utc and tz.normalize() or can you use datetime.now(tz) instead?

+0

Il suo obiettivo è dare un esempio sulla pagina principale del progetto di come usare 'Delorean' è più pulito che usare' datetime' e 'pytz'. È un cattivo esempio perché è un codice errato e può essere gestito meglio dal tuo esempio, ma il tuo esempio non raggiunge l'obiettivo originale. Forse proporre un nuovo esempio che mostri un caso in cui 'localize' e' normalize' siano effettivamente necessari e come sia più facilmente gestito con un 'Delorean'? – heenenee

+1

Ho archiviato un [problema] (https://github.com/myusuf3/delorean/issues/70) con delorean, quindi hanno creato una [richiesta pull] (https://github.com/myusuf3/delorean/pull/ 71/files) che pulisce il primo esempio. (Hanno anche pulito l'esempio delorean.) –

+0

@heenenee: la mia domanda riguarda 'datetime.now (tz)': se puoi sempre usarlo per restituire l'ora corrente in un determinato fuso orario invece di est.normalize (utc .localize (datetime.uctnow()). astimezone (est)) '. – jfs

risposta

9

Quando si fa datetime.now(pytz_timezone) falliscono?

Per quanto posso dire, non ci sono scenari in cui potrebbe fallire. datetime.now richiama la funzione fromutc sull'istanza tzinfo passata nel parametro. Tutte le conversioni da UTC a ora locale non sono ambigue, quindi non ci sono opportunità di fallimento.

Inoltre, il codice originale non funziona nemmeno.

d = est.normalize(EST) 

Ciò sembrerebbe passare una stringa come unico parametro normalize, che è destinato a prendere un datetime. Questo dà:

AttributeError: 'str' object has no attribute 'tzinfo' 

Credo che lo scopo di scrivere:

d = est.normalize(d.astimezone(est)) 

Detto questo, non credo che la verbosità del loro codice aggiunge molto valore. Come avrete notato, è altrettanto facile fare questo in un unico passaggio:

d = datetime.now(est) 

Guardando il cpython source code for datetime.now, posso vedere che, quando è previsto un oggetto tzinfo, si chiama il metodo fromutc su tale oggetto.

if (self != NULL && tz != Py_None) { 
    /* Convert UTC to tzinfo's zone. */ 
    PyObject *temp = self; 

    self = _PyObject_CallMethodId(tz, &PyId_fromutc, "O", self); 
    Py_DECREF(temp); 
} 

Poi, nella sorgente pytz, vedo che il metodo è implementato fromutc diverso a seconda che la zona è pytz.UTC, oppure un'istanza di StaticTzInfo o DstTzInfo. In tutti e tre i casi, la trasformazione dal valore UTC di input al fuso orario target non è ambigua.Ecco l'implementazione DstTzInfo, che è il più complesso dei tre:

def fromutc(self, dt): 
    '''See datetime.tzinfo.fromutc''' 
    if (dt.tzinfo is not None 
     and getattr(dt.tzinfo, '_tzinfos', None) is not self._tzinfos): 
     raise ValueError('fromutc: dt.tzinfo is not self') 
    dt = dt.replace(tzinfo=None) 
    idx = max(0, bisect_right(self._utc_transition_times, dt) - 1) 
    inf = self._transition_info[idx] 
    return (dt + inf[0]).replace(tzinfo=self._tzinfos[inf]) 

Questo sembrerebbe trovare il passaggio dalla _utc_transition_times del fuso orario, poi applicarlo alla restituita datetime. Non ci sono ambiguità in questa direzione, quindi i risultati saranno equivalenti.

Vale anche la pena notare, in the datetime docs si dice che datetime.now è equivalente a chiamare:

tz.fromutc(datetime.utcnow().replace(tzinfo=tz)) 

Data la fonte di fromutc in pytz ho mostrato in precedenza, non sono sicuro che questo è diverso non solo:

tz.fromutc(datetime.utcnow()) 

Ma in entrambi i casi, non credo che localize e normalize sono necessari.

Problemi correlati