Python timetime.datetime来自time.structtime的差异

时间:2015-08-01 20:45:00

标签: python timestamp python-datetime

我使用feedparser从一些RSS提要中获取条目。 这些条目有一个published_pa​​rsed字段,由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 个答案:

答案 0 :(得分:1)

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

  

返回与POSIX时间戳对应的本地日期和时间,例如time.time()返回的日期和时间。如果可选参数tz为None或未指定,则时间戳将转换为平台的本地日期和时间,并且返回的datetime对象是天真的

然后field tm_isdst=0告诉它不使用夏令时(尽管当地时区使用它),可以解释1小时的差异。

为了更清楚地看到这一点,我们构建了两个测试用例

glob.glob

输出如下:

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 的{​​{1}}对象有structTime,但您要解析的时间戳是DST时区。

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

答案 1 :(得分:1)

calendar.timegm UTC timetuple作为输入并返回其时间戳。 相反,time.mktime local timetuple作为输入并返回其(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