Как преобразовать объект time.struct_time в объект datetime?

288

Как конвертировать time.struct_timeобъект Python в datetime.datetimeобъект?

У меня есть библиотека, которая предоставляет первую и вторую библиотеку, которая хочет вторую.

static_rtti
источник

Ответы:

384

Используйте time.mktime (), чтобы преобразовать кортеж времени (по местному времени) в секунды с начала эпохи, затем используйте datetime.fromtimestamp (), чтобы получить объект datetime.

from datetime import datetime
from time import mktime

dt = datetime.fromtimestamp(mktime(struct))
Род Хайд
источник
45
Обратите внимание, что до 1900 года это не получится. Вы, современные люди, никогда не помните этого ограничения!
mlissner
3
это потеряет tm_isdstданные? Я думаю , что это так, в результате чего DATETIME объект остается наивным до такой степени , чтобы вернуться Noneна , .dst()даже если struct.tm_isdstэто 1.
n611x007
3
Это обычно будет работать. Однако произойдет сбой, если кортеж времени превышает значения, которые принимает mktime, например, для значения (1970, 1, 1, 0, 0, 0, 0, 1, -1). Я столкнулся с этим после синтаксического анализа заголовка Date HTTP-запроса, который вернул этот кортеж.
user3820547
3
@richvdh: стандарт C определяет, что mktime()следует tm_isdstучитывать, и Python time.mktime()вызывает mktime()функцию C на CPython. mktime()может выбрать неправильное местное время, когда оно неоднозначно (например, во время перехода в конце DST («откат»)), если struct.tm_isdstесть -1или если mktime()на данной платформе игнорирует ввод tm_isdst . Кроме того, если в прошлом местный часовой пояс имел различное смещение utc в прошлом, и C mktime()не использует историческую базу данных tz, которая может предоставить старые значения смещения utc, то mktime()может также вернуть неправильное (например, на час) значение.
JFS
1
@naxa: если mktime()не игнорировать tm_isdstна данной платформе (это делает на моей), то, fromtimestamp()безусловно, теряет информацию: возвращаемый наивный datetime объект, представляющий местное время, может быть неоднозначным (timestamp -> local time является детерминированным (если мы игнорируем високосные секунды), но local time -> timestamp may be ambiguous e.g., during end-of-DST transition). Also, fromtimestamp () `может выбрать неправильное смещение utc, если оно не использует историческую базу данных tz.
jfs
123

Как это:

>>> structTime = time.localtime()
>>> datetime.datetime(*structTime[:6])
datetime.datetime(2009, 11, 8, 20, 32, 35)
Надя Алрамли
источник
3
Не забудьте импортировать время,
дату и
7
@jhwist - некоторые вещи, которым можно доверять, чтобы понять это самостоятельно :)
orip
14
@rodling *и **синтаксис позволяет вам расширить объект типа listy или dicty для разделения аргументов - это одна из моих любимых частей Python. См. Docs.python.org/2/tutorial/… для получения дополнительной информации
OrganicPanda
10
Просто помните, что это даст вам ValueError, если struct_time имеет дополнительную секунду, например:t=time.strptime("30 Jun 1997 22:59:60", "%d %b %Y %H:%M:%S"); datetime.datetime(*t[:6])
berdario
7
@berdario: вернуть значения, совместимые с datetime: datetime(*t[:5]+(min(t[5], 59),))например, принять "2015-06-30 16:59:60 PDT".
Jfs
37

Это не прямой ответ на ваш вопрос (на который уже довольно неплохо ответили). Однако, несколько раз укусив меня за фундамент, я не могу не подчеркнуть, что вам следует внимательно присмотреться к тому, что предоставляет ваш объект time.struct_time, по сравнению с другими временными полями.

Предполагая, что у вас есть как объект time.struct_time, так и некоторая другая строка даты / времени, сравните их и убедитесь, что вы не теряете данные и случайно создаете наивный объект datetime, если вы можете сделать иначе.

Например, отличный модуль feedparser возвратит «опубликованное» поле и может вернуть объект time.struct_time в свое поле «ключ_публикованного»:

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)

Теперь обратите внимание, что вы на самом деле получаете с «опубликованным» полем.

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

По Stallman Борода «s! Информация о часовом поясе!

В этом случае ленивый человек может захотеть использовать отличный модуль dateutil для хранения информации о часовом поясе:

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

что дает нам:

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

Затем можно использовать объект datetime с учетом часового пояса, чтобы нормализовать все время по UTC или что-то еще, что вы считаете удивительным.

lysdexia
источник
7
Все *_parsedполя из feedparsed уже нормализованы к UTC, что можно проверить в документации разбора даты, так что это избыточно.
itorres
1
@itorres: Если я понимаю, этот ответ не о нормализации к UTC, а о хранении информации о часовом поясе в datetimeобъекте, который теряется при feedparserразборе необработанных строковых дат.
Давидаг