Python datetime.datetime от time.structtime разница
Я использую feedparser, чтобы получить записи из некоторых RSS-каналов. Записи имеют поле publ_parsed, которое анализирует feedparser в time.structtime.
Я использую эту функцию для преобразования time.structtime в datetime.datetime:
def publishParsedToDatetime(structTime):
return datetime.datetime.fromtimestamp(time.mktime(structTime))
Вход (structtime):
time.struct_time(tm_year=2015, tm_mon=8, tm_mday=1, tm_hour=20, tm_min=28, tm_sec=33, tm_wday=5, tm_yday=213, tm_isdst=0)
Выход (дата-время):
2015-08-01 21:28:33
Я вижу проблему, которая может быть связана с часовым поясом, разница между значениями structtime и datetime составляет 1 час.
Значение structtime - UTC. Но значение datetime.datetime не является ни UTC, ни моим текущим часовым поясом (CET, центральноевропейское время, мы наблюдаем летнее время, поэтому у нас сейчас UTC + 2 часа).
Как это можно объяснить?
2 ответа
На самом деле, как объяснено в документации дляdatetime.fromtimestamp
по умолчанию конвертируется в местное время:
Возвращает локальную дату и время, соответствующие метке времени POSIX, например, возвращается time.time(). Если необязательный аргумент tz равен None или не указан, отметка времени преобразуется в локальные дату и время платформы, а возвращаемый объект datetime является наивным
Разница в 1 час может быть объяснена полемtm_isdst=0
говорит, что не использовать летнее время (несмотря на то, что вы используете местный часовой пояс).
Чтобы увидеть это более четко, мы построим два теста
import time, datetime
# this is how your time object was constructed before
tm_isdst = 0
t = time.mktime((2015, 8, 1, 20, 28, 33, 5, 213, tm_isdst))
print("Old conversion: {0}".format(datetime.datetime.fromtimestamp(t)))
# this is what happens if you let mktime "divine" a time zone
tm_isdst = -1
t = time.mktime((2015, 8, 1, 20, 28, 33, 5, 213, tm_isdst))
print("New conversion: {0}".format(datetime.datetime.fromtimestamp(t)))
Результат этого следующий:
Old conversion: 2015-08-01 21:28:33
New conversion: 2015-08-01 20:28:33
Проблема тогда, вы видите, в том, что structTime
объект передается вашему publishParsedToDatetime
имеет tm_isdst=0
но метка времени, которую вы хотели проанализировать, была для часового пояса DST.
Как вы уже отметили в другом комментарии, правильное решение этой проблемы, вероятно, состоит в том, чтобы всегда использовать UTC в вашем внутреннем коде и выполнять обработку часового пояса только при отображении времени пользователю или при чтении пользовательского ввода.
calendar.timegm
принимает в качестве входных данных временную шкалу UTC и возвращает свою временную метку. По сравнению, time.mktime
принимает в качестве входных данных локальное время и возвращает его (UTC) метку времени. Все метки времени представляют секунды с начала эпохи 1970-1-1 00:00:00 UTC.
utcfromtimestamp
принимает в качестве входных данных временную метку и преобразует ее в наивную (т.е. не зависящую от часового пояса) дату и время UTC. fromtimestamp
берет ту же временную метку и преобразует ее в соответствующую наивную локальную дату и время.
Поскольку ваши расписания (например, structTime
) являются UTC, вы должны использовать calendar.timegm
не time.mktime
, чтобы найти правильную метку времени. Как только у вас есть правильная метка времени, fromtimestamp
вернет соответствующее наивное местное время.
import time
import calendar
import datetime as DT
timetuple = (2015, 8, 1, 20, 28, 33, 5, 213, 0)
timestamp = calendar.timegm(timetuple)
naive_local_date = DT.datetime.fromtimestamp(timestamp)
print('Naive local: {}'.format(naive_local_date))
доходность
Naive local: 2015-08-01 22:28:33