Bagaimana Anda mengonversi objek time.struct_time menjadi objek datetime?

288

Bagaimana Anda mengubah time.struct_timeobjek Python menjadi datetime.datetimeobjek?

Saya memiliki perpustakaan yang menyediakan perpustakaan pertama dan perpustakaan kedua yang menginginkan perpustakaan kedua.

static_rtti
sumber

Jawaban:

384

Gunakan time.mktime () untuk mengubah tuple waktu (dalam localtime) menjadi detik sejak Zaman, kemudian gunakan datetime.fromtimestamp () untuk mendapatkan objek datetime.

from datetime import datetime
from time import mktime

dt = datetime.fromtimestamp(mktime(struct))
Batang Hyde
sumber
45
Perhatikan bahwa ini gagal sebelum 1900. Anda orang modern tidak pernah ingat batasan ini!
mlissner
3
apakah ini akan kehilangan tm_isdstdata? Saya kira begitu, yang dihasilkan objek datetime tetap naif untuk sejauh kembali Nonepada .dst()bahkan jika struct.tm_isdstini 1.
n611x007
3
Ini biasanya akan berhasil. Namun, itu akan gagal jika tuple waktu di luar nilai yang diterima mktime, misalnya untuk nilai (1970, 1, 1, 0, 0, 0, 0, 0, 1, -1). Saya mengalami ini setelah mem-parsing header Date pada permintaan HTTP yang mengembalikan tuple ini.
user3820547
3
@richvdh: Standar C menentukan yang mktime()harus tm_isdstmempertimbangkan dan Python time.mktime()memanggil mktime()fungsi C pada CPython. mktime()dapat memilih waktu setempat salah ketika itu adalah ambigu (misalnya, selama akhir-of-DST ( "jatuh kembali") transisi) jika struct.tm_isdstini -1atau jika mktime()pada platform yang diberikan mengabaikan masukan tm_isdst . Juga, jika zona waktu lokal memiliki offset utc yang berbeda di masa lalu dan C mktime()tidak menggunakan basis data tz historis yang dapat memberikan nilai offset utc yang lama, maka mktime()dapat mengembalikan nilai yang salah (misalnya, satu jam) juga.
jfs
1
@naxa: jika mktime()tidak mengabaikan tm_isdstplatform yang diberikan (itu terjadi pada saya) maka fromtimestamp()pasti kehilangan info: objek naif yang dikembalikan datetimemewakili waktu lokal mungkin ambigu (timestamp -> waktu lokal adalah deterministik (jika kita mengabaikan detik kabisat) tetapi local time -> timestamp may be ambiguous e.g., during end-of-DST transition). Also, fromtimestamp () `dapat memilih offset utc yang salah jika tidak menggunakan basis data tz historis
jfs
123

Seperti ini:

>>> structTime = time.localtime()
>>> datetime.datetime(*structTime[:6])
datetime.datetime(2009, 11, 8, 20, 32, 35)
Nadia Alramli
sumber
3
Jangan lupa untuk #meminta waktu, datetime
jhwist
7
@jhwist - beberapa hal orang dapat dipercaya untuk mengetahuinya sendiri :)
orip
14
@membawa *dan **sintaks memungkinkan Anda untuk memperluas objek tipe listy atau dicty ke argumen yang terpisah - itu salah satu bagian favorit saya dari Python lovelyness. Lihat docs.python.org/2/tutorial/… untuk info lebih lanjut
OrganicPanda
10
Ingat saja ini akan memberi Anda ValueError jika struct_time memiliki lompatan, misalnya:t=time.strptime("30 Jun 1997 22:59:60", "%d %b %Y %H:%M:%S"); datetime.datetime(*t[:6])
berdario
7
@berdario: untuk mengembalikan nilai yang kompatibel dengan datetime: datetime(*t[:5]+(min(t[5], 59),))misalnya, untuk menerima "2015-06-30 16:59:60 PDT".
jfs
37

Ini bukan jawaban langsung untuk pertanyaan Anda (yang sudah dijawab dengan cukup baik). Namun, setelah beberapa kali menggigit saya pada dasar beberapa kali, saya tidak bisa cukup menekankan bahwa itu akan mendorong Anda untuk melihat dengan cermat apa yang disediakan waktu Anda.

Dengan asumsi Anda memiliki objek time.struct_time, dan beberapa string tanggal / waktu lainnya, bandingkan keduanya, dan pastikan Anda tidak kehilangan data dan secara tidak sengaja membuat objek datetime yang naif, ketika Anda bisa melakukan sebaliknya.

Misalnya, modul feedparser yang sangat baik akan mengembalikan bidang "diterbitkan" dan dapat mengembalikan objek time.struct_time dalam bidang "publish_parsed" -nya:

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)

Sekarang perhatikan apa yang sebenarnya Anda dapatkan dengan bidang "diterbitkan".

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

Oleh Stallman 's Beard! Informasi zona waktu!

Dalam hal ini, pria malas mungkin ingin menggunakan modul dateutil yang sangat baik untuk menjaga informasi zona waktu:

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

yang memberi kita:

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

Seseorang kemudian dapat menggunakan objek waktu-sadar datzone untuk menormalkan semua waktu ke UTC atau apa pun yang Anda anggap mengagumkan.

lysdexia
sumber
7
Semua *_parsedbidang dari feedparsed sudah dinormalisasi ke UTC karena dapat diperiksa dalam dokumentasi parsing tanggal sehingga ini mubazir.
itorres
1
@itorres: Jika saya memahaminya, jawaban ini bukan tentang menormalkan ke UTC, tetapi tentang menjaga informasi zona waktu di datetimeobjek yang hilang ketika feedparsermem-parsing tanggal string mentah.
davidag