Python 与 time.structtime 的区别 datetime.datetime

Python datetime.datetime from time.structtime difference

我使用 feedparser 从一些 RSS 提要中获取条目。 这些条目有一个 published_parsed 字段,由 feedparser 解析为 time.structtime.

我用这个函数把time.structtime转换成datetime.datetime:

def publishParsedToDatetime(structTime): 
    return datetime.datetime.fromtimestamp(time.mktime(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 + 2hrs)。

这怎么解释?

实际上,如documentation for datetime.fromtimestamp中所述,它默认转换为本地时间:

Return the local date and time corresponding to the POSIX timestamp, such as is returned by time.time(). If optional argument tz is None or not specified, the timestamp is converted to the platform’s local date and time, and the returned datetime object is naive

1 小时的差异可以解释为 field 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

然后,你看,问题是传递给你的 publishParsedToDatetimestructTime 对象有 tm_isdst=0 但你想要解析的时间戳是 DST 时区.

正如您在另一条评论中已经指出的那样,正确的解决方案可能是始终在后端代码中使用 UTC,并且仅在向用户显示时间或读取用户时才进行时区处理输入。

calendar.timegmUTC 时间元组作为输入,return 是它的时间戳。 相反,time.mktimelocal 时间元组作为输入,return 是它的 (UTC) 时间戳。所有时间戳代表自 Epoch 以来的秒数,1970-1-1 00:00:00 UTC。

utcfromtimestamp 将时间戳作为输入并将其转换为朴素的 (即时区未知)UTC 日期时间。 fromtimestamp取同一个时间戳,转换成对应的 天真的本地日期时间。

由于您的时间元组(例如 structTime)是 UTC 时间元组,您应该使用 calendar.timegm 而不是 time.mktime 来找到正确的时间戳。 一旦你有了正确的时间戳,fromtimestamp 将 return 相应的原始本地日期时间。


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