2015-08-07 7 views
9

delorean docs zeigen auf diese Weise in einer bestimmten Zeitzoneusing datetime die aktuelle Zeit erhalten:Wann schlägt `datetime.now (pytz_timezone)` fehl?

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) 

und vergleicht ihn mit dem Delorian-basierten Code:

from delorean import Delorean 

EST = "US/Eastern" 

d = Delorean(timezone=EST) 

I believe das datetime Beispiel geschrieben werden soll wie:

from datetime import datetime 
import pytz 

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

das ist prägnanter.

Gibt es Fälle, in denen das letzte Codebeispiel fehlschlägt, während das erste weiterhin funktioniert?


Update: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 

, die noch zu ausführlich ist.

Die Frage Stills steht: do you need the explicit round-trip via utc and tz.normalize() or can you use datetime.now(tz) instead?

+0

Sein Ziel ist es, auf der Hauptseite des Projekts ein Beispiel zu geben, wie die Verwendung eines 'Delorean' sauberer ist als die Verwendung von' datetime' und 'pytz'. Es ist ein schlechtes Beispiel, weil es sich um falschen Code handelt, der in Ihrem Beispiel besser behandelt werden kann, aber Ihr Beispiel entspricht nicht dem ursprünglichen Ziel. Vielleicht ein neues Beispiel vorschlagen, das einen Fall zeigt, in dem "localize" und "normalize" tatsächlich notwendig sind und wie man es mit einem 'Delorean' einfacher handhaben kann? – heenenee

+1

Ich habe ein [Problem] (https://github.com/myusuf3/delorean/issues/70) mit delorean eingereicht, also haben sie eine [pull request] erstellt (https://github.com/myusuf3/delorean/pull/ 71/files), die das erste Beispiel aufräumt. (Sie haben auch das Delorean Beispiel aufgeräumt.) –

+0

@heenenee: meine Frage ist über 'datetime.now (tz)': ob Sie es immer verwenden können, um die aktuelle Zeit in einer bestimmten Zeitzone anstelle von 'est.normalize (utc .localize (datetime.uctnow()). astimezone (est)) '. – jfs

Antwort

9

Wann datetime.now(pytz_timezone) scheitern?

Soweit ich sagen kann, gibt es keine Szenarien, in denen es fehlschlagen könnte. datetime.now ruft die fromutc-Funktion auf der tzinfo Instanz auf, die in dem Parameter übergeben wird. Alle Konvertierungen von UTC in Ortszeit sind eindeutig, daher gibt es keine Möglichkeiten zum Scheitern.

Auch der ursprüngliche Code funktioniert nicht einmal.

d = est.normalize(EST) 

Dies scheint eine Zeichenfolge als einzigen Parameter normalize passieren, die eine datetime tragen soll. Dies ergibt:

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

Ich glaube, sie zu schreiben bedeutete:

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

Das heißt, ich glaube nicht, das Ausführlichkeit ihres Codes viel Wert hinzufügt. Wie Sie bemerkt, ist es genauso einfach diese in einem einzigen Schritt zu tun:

d = datetime.now(est) 

am cpython source code for datetime.now Sehen, kann ich sehen, dass, wenn ein tzinfo Objekt zur Verfügung gestellt wird, ist es die fromutc Methode für das Objekt aufruft.

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); 
} 

Dann wird in der pytz Quelle, sehe ich, dass die Methode fromutc verschieden bei geführt wird je nachdem, ob die Zone pytz.UTC, oder eine Instanz StaticTzInfo oder DstTzInfo. In allen drei Fällen ist die Transformation vom eingegebenen UTC-Wert zur Zielzeitzone eindeutig.Hier ist die DstTzInfo Implementierung, die je komplexer der drei ist:

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]) 

Dies scheint den Übergang von _utc_transition_times der Zeitzone zu finden, dann wenden sie auf die zurück datetime. Es gibt keine Unklarheiten in dieser Richtung, so dass die Ergebnisse gleichwertig sind.

auch erwähnenswert, in the datetime docs es sagt, dass datetime.now dem Aufruf entspricht:

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

die Quelle fromutc in pytz Da ich früher zeigte, bin ich nicht sicher, dass dies nicht nur anders ist:

tz.fromutc(datetime.utcnow()) 

Aber in jedem Fall, glaube ich nicht, localize und normalize notwendig sind.