Jak przekonwertować obiekt time.struct_time na obiekt datetime?

288

Jak przekonwertować time.struct_timeobiekt Python na datetime.datetimeobiekt?

Mam bibliotekę, która udostępnia pierwszą i drugą bibliotekę, która chce drugiej.

static_rtti
źródło

Odpowiedzi:

384

Użyj time.mktime (), aby przekonwertować krotkę czasu (w czasie lokalnym) na sekundy od Epoki, a następnie użyj datetime.fromtimestamp (), aby uzyskać obiekt datetime.

from datetime import datetime
from time import mktime

dt = datetime.fromtimestamp(mktime(struct))
Rod Hyde
źródło
45
Pamiętaj, że to się nie powiedzie przed 1900 rokiem. Wy, ludzie, nigdy nie pamiętasz tego ograniczenia!
mlissner
3
czy to spowoduje utratę tm_isdstdanych? Myślę, że tak otrzymany datetime obiekt pozostaje naiwny do tego stopnia, aby powrócić Nonena .dst()nawet jeśli struct.tm_isdstjest 1.
n611x007
3
To zwykle działa. Jednak nie powiedzie się, jeśli krotność czasu przekroczy wartości zaakceptowane przez mktime, na przykład dla wartości (1970, 1, 1, 0, 0, 0, 0, 1, -1). Napotkałem to po przeanalizowaniu nagłówka Date w żądaniu HTTP, które zwróciło tę krotkę.
user3820547,
3
@richvdh: C standard określa, że mktime()należy wziąć tm_isdstpod uwagę, a Python time.mktime()wywołuje mktime()funkcję C na CPython. mktime()może wybrać niewłaściwy czas lokalny, gdy jest niejednoznaczny (np. podczas przejścia na koniec DST („cofnięcia”)), jeśli struct.tm_isdstjest -1lub jeśli mktime()na danej platformie ignoruje dane wejściowe tm_isdst . Ponadto, jeśli lokalna strefa czasowa miała w przeszłości inne przesunięcie utc, a C mktime()nie korzysta z historycznej bazy danych tz, która może dostarczyć stare wartości przesunięcia utc, wówczas mktime()może zwrócić również niepoprawną (np. O godzinę) wartość.
jfs
1
@naxa: jeśli mktime()nie ignoruje tm_isdstna danej platformie (działa na mojej), to fromtimestamp()zdecydowanie traci informacje: zwrócony naiwny datetime obiekt reprezentujący czas lokalny może być niejednoznaczny (znacznik czasu -> czas lokalny jest deterministyczny (jeśli zignorujemy sekundy przestępne), ale local time -> timestamp may be ambiguous e.g., during end-of-DST transition). Also, fromtimestamp () `może wybrać nieprawidłowe przesunięcie utc, jeśli nie korzysta ono z historycznej bazy danych tz.
jfs
123

Lubię to:

>>> structTime = time.localtime()
>>> datetime.datetime(*structTime[:6])
datetime.datetime(2009, 11, 8, 20, 32, 35)
Nadia Alramli
źródło
3
Nie zapomnij o #import time, datetime
jhwist
7
@jhwist - niektórym ludziom można ufać, że sami to
wymyślą
14
@rodling *i **składnia pozwala rozwinąć obiekt typu listy lub dicty w celu oddzielenia argumentów - jest to jeden z moich ulubionych elementów uwielbienia Pythona. Aby uzyskać więcej informacji, zobacz docs.python.org/2/tutorial/…
OrganicPanda
10
Pamiętaj tylko, że to da ci błąd ValueError, jeśli struct_time ma upływ czasu, np .:t=time.strptime("30 Jun 1997 22:59:60", "%d %b %Y %H:%M:%S"); datetime.datetime(*t[:6])
berdario
7
@berdario: aby zwrócić wartości zgodne z datetime: datetime(*t[:5]+(min(t[5], 59),))np "2015-06-30 16:59:60 PDT". zaakceptować .
jfs
37

To nie jest bezpośrednia odpowiedź na twoje pytanie (na które już dość dobrze odpowiedziano). Jednak po kilkakrotnym ugryzieniu mnie w podstawę nie mogę wystarczająco podkreślić, że byłoby dobrze, gdybyś dokładnie przyjrzał się temu, co zapewnia Twój obiekt time.struct_time, a co inne pola czasu mogą mieć.

Zakładając, że masz zarówno obiekt time.struct_time, jak i inny ciąg daty / godziny, porównaj je i upewnij się, że nie tracisz danych i nieumyślnie tworzysz naiwny obiekt daty / godziny, jeśli możesz zrobić inaczej.

Na przykład doskonały moduł Feedparser zwróci pole „opublikowany” i może zwrócić obiekt time.struct_time w polu „opublikowany”:

time.struct_time(tm_year=2013, tm_mon=9, tm_mday=9, tm_hour=23, tm_min=57, tm_sec=42, tm_wday=0, tm_yday=252, tm_isdst=0)

Teraz zwróć uwagę na to, co faktycznie otrzymujesz w polu „opublikowany”.

Mon, 09 Sep 2013 19:57:42 -0400

Na brodę Stallmana ! Informacje o strefie czasowej!

W takim przypadku leniwy człowiek może chcieć użyć doskonałego modułu dateutil do zachowania informacji o strefie czasowej:

from dateutil import parser
dt = parser.parse(entry["published"])
print "published", entry["published"])
print "dt", dt
print "utcoffset", dt.utcoffset()
print "tzinfo", dt.tzinfo
print "dst", dt.dst()

co daje nam:

published Mon, 09 Sep 2013 19:57:42 -0400
dt 2013-09-09 19:57:42-04:00
utcoffset -1 day, 20:00:00
tzinfo tzoffset(None, -14400)
dst 0:00:00

Następnie można użyć obiektu datetime rozpoznającego strefę czasową, aby znormalizować cały czas do UTC lub cokolwiek, co uważasz za niesamowite.

lysdeksja
źródło
7
Wszystkie *_parsedpola z feedparsed są już znormalizowane do UTC, co można sprawdzić w dokumentacji parsowania daty, więc jest to zbędne.
itorres
1
@itorres: Jeśli rozumiem, ta odpowiedź nie dotyczy normalizacji do UTC, ale przechowywania informacji o strefie czasowej w datetimeobiekcie, który jest tracony podczas feedparseranalizy nieprzetworzonych dat ciągu.
davidag