2012-11-06 11 views
25

Próbuję napisać parę funkcji, dt i ut, które konwertują w przód i w tył między normalnym czasem unixa (sekundy od 1970-01-01 00:00:00 UTC) i obiekt datetime Pythona.Konwertuj czas uniksowy na obiekt typu datetime iz powrotem (pary funkcji konwersji czasu, które są odwrotne)

Jeśli dt i ut były odpowiednie odwrotne czym ten kod to drukowania tego samego znacznika czasu dwukrotnie:

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

Niestety, drugi znacznik czasu wynosi 3600 sekund (godzinę) mniej niż pierwszy. Wydaje mi się, że dzieje się tak tylko w bardzo szczególnych sytuacjach, może w tej godzinie czas letni przestaje działać. Ale czy istnieje sposób na napisanie dt i ut, więc są one prawdziwymi odwrotnościami siebie nawzajem?

Powiązane pytanie: Making matplotlib's date2num and num2date perfect inverses

+0

BTW, jeśli funkcja nic nie robi, ale wywołuje inną funkcję z te same argumenty, które można następnie przypisać: 'dt = datetime.datetime.utcfromtimestamp'. Funkcje są pierwszorzędnymi obywatelami w Pythonie: możesz przekazać je jako parametry do innych funkcji, powrócić z funkcji itp. – jfs

+0

Ach, ładny, świetny punkt! Czy jest to bardziej efektywne, czy tylko kwestia zwięzłości? A co z 'def f (x): return foo (x)' vs 'f = lambda x: foo (x)'? (Moim wspomnieniem jest to, że są one równoważne, zarówno pod względem funkcjonalnym, jak i pod względem wydajności). – dreeves

+0

'f = g' oznacza, że ​​f, g to dwie nazwy odnoszące się do tej samej funkcji. 'def' i' lambda' tworzą nową funkcję. – jfs

Odpowiedz

37

Masz rację, że to zachowanie jest związane z czasu letniego. Najprostszym sposobem na uniknięcie tego jest zagwarantowanie, że korzystasz ze strefy czasowej bez zmiany czasu, UTC ma tutaj największy sens.

datetime.datetime.utcfromtimestamp() i calendar.timegm() dotyczą czasu UTC i są dokładnymi odwrotnościami.

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

Tutaj jest trochę wyjaśnienie za dlaczego datetime.datetime.fromtimestamp() ma problem z czasu letniego, od docs:

Zwraca lokalną datę i czas odpowiadający datownik POSIX taki jak jest zwrócony przez time.time(). Jeśli opcjonalny argument tz jest Brak lub , nie jest określony, znacznik czasu jest konwertowany na lokalną datę platformy i czas, a zwracany obiekt datetime jest naiwny.

Ważną częścią jest to, że masz naiwne datetime.datetime przedmiot, który oznacza brak stref czasowych (lub letni) informacje jako część obiektu. Oznacza to, że wiele odrębnych timestamps można mapować do tego samego datetime.datetime obiektu przy użyciu fromtimestamp(), jeśli zdarzy ci się wybrać czasy, które spadają podczas letniego czasu rolce tylnej:

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

Idealny; dzięki! (I potwierdziłem, że to działa dla mnie.) – 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, chcesz dodać to jako odpowiedź? Wygląda na to, że masz rację (chociaż nie zweryfikowałem twojej wersji), a twoja powinna być tutaj zaakceptowaną odpowiedzią. Nienawidzę poprowadzić potomków na manowce, mając tylko link w komentarzach wskazujących na lepszy sposób! – dreeves

Powiązane problemy