2012-11-06 5 views
25

Ich versuche ein Paar Funktionen zu schreiben, dt und ut, die zwischen normaler Unixzeit (Sekunden seit 1970-01-01 00:00:00 UTC) und ein Python-Datetime-Objekt.Konvertiere ein unixtime in ein datetime Objekt und wieder zurück (Paar Zeitumwandlungsfunktionen, die inversen sind)

Wenn dt und ut richtige Umkehrungen waren dann würde dieser Code den gleichen Zeitstempel zweimal drucken:

import time, datetime 

# Convert a unix time u to a datetime object d, and vice versa 
def dt(u): return datetime.datetime.fromtimestamp(u) 
def ut(d): return time.mktime(d.timetuple()) 

u = 1004260000 
print u, "-->", ut(dt(u)) 

Ach, der zweite Zeitstempel beträgt 3600 Sekunden (eine Stunde) kleiner als der erste. Ich denke, das passiert nur für ganz bestimmte unixtimes, vielleicht während dieser Stunde, die Sommerzeit überspringt. Aber gibt es eine Möglichkeit, dt und ut zu schreiben, so dass sie wahre Inverse voneinander sind?

Verwandte Frage: Making matplotlib's date2num and num2date perfect inverses

+0

btw, wenn die Funktion nichts tut, sondern ruft eine andere Funktion mit die gleichen Argumente können Sie dann einfach zuweisen: 'dt = datetime.datetime.utcfromtimestamp'. Funktionen sind erstklassige Bürger in Python: Sie können sie als Parameter an andere Funktionen übergeben, von Funktionen zurückkehren, etc. – jfs

+0

Ah, schön, toller Punkt! Ist es effizienter oder nur eine Frage der Prägnanz? Was ist mit 'def f (x): Rückkehr foo (x)' vs 'f = Lambda x: foo (x)'? (Meine Erinnerung ist, dass diese sowohl funktional als auch in Bezug auf die Effizienz äquivalent sind.) – dreeves

+0

"f = g" bedeutet, dass f, g zwei Namen sind, die sich auf die gleiche Funktion beziehen. 'def' und' lambda' erzeugen neue Funktionen. – jfs

Antwort

37

Sie sind richtig, dass dieses Verhalten auf die Sommerzeit in Beziehung steht. Der einfachste Weg, dies zu vermeiden, ist sicherzustellen, dass Sie eine Zeitzone ohne Sommerzeit verwenden, UTC ist hier am sinnvollsten.

datetime.datetime.utcfromtimestamp() und calendar.timegm() befassen sich mit UTC-Zeiten und sind genaue Inverse.

import calendar, datetime 

# Convert a unix time u to a datetime object d, and vice versa 
def dt(u): return datetime.datetime.utcfromtimestamp(u) 
def ut(d): return calendar.timegm(d.timetuple()) 

ist hier ein bisschen Erklärung hinter warum datetime.datetime.fromtimestamp() ein Problem mit der Sommerzeit hat, von der Dokumentation:

Rückkehr der lokale Datum und die Uhrzeit zu dem Zeitstempel POSIX entspricht, wie ist zurückgegeben von time.time(). Wenn das optionale Argument tz keine oder nicht angegeben ist, wird der Zeitstempel in das lokale Datum der Plattform und die Uhrzeit konvertiert, und das zurückgegebene datetime-Objekt ist naiv.

Der wichtige Teil ist, dass Sie ein naives datetime.datetime Objekt bekommen, was bedeutet, dass es keine Zeitzone (oder Sommer) Informationen als Teil des Objekts. Dies bedeutet, dass mehrere verschiedene Zeitstempel auf dem gleichen datetime.datetime Objekt abbilden kann, wenn fromtimestamp() verwenden, wenn Sie während der Sommerzeit Rolle zurückfallen passieren Zeiten auszuwählen, die:

>>> datetime.datetime.fromtimestamp(1004260000) 
datetime.datetime(2001, 10, 28, 1, 6, 40) 
>>> datetime.datetime.fromtimestamp(1004256400) 
datetime.datetime(2001, 10, 28, 1, 6, 40) 
+0

Perfekt; Vielen Dank! (Und ich habe bestätigt, dass es für mich funktioniert.) – dreeves

+0

['ut = lambda naive_utc_dt: (naive_utc_dt - datetime (1970,1,1)) .total_seconds()'] (http://stackoverflow.com/a/ 8778548/4279) – jfs

+0

@JFSebastian, möchten Sie das als Antwort hinzufügen? Es klingt, als hättest du recht (obwohl ich deine Version nicht verifiziert habe) und deine sollte die akzeptierte Antwort hier sein. Ich hasse es, die Nachwelt in die Irre zu führen, mit nur einem Verweis in den Kommentaren auf einen besseren Weg! – dreeves