使用datetime 处理数据时间时最好带上时区信息
Anebrithien opened this issue · 3 comments
Anebrithien commented
CinradReader
的 scantime
是没有指定 tzinfo
属性的 datetime.datetime
对象,在对这个对象调用 timestamp()
等一些与操作系统所在时区有关的函数时,会出现意料之外的情况。
观察代码发现,认定了雷达数据里的日期时间是UTC+8的,所以做了减去8小时的操作,手动将它变成UTC日期时间。
代码片段:
Line 23 in b2dc3c5
Lines 220 to 230 in b2dc3c5
下面是一个简单示例:
>>> import datetime
>>> original_time = datetime.datetime(2014, 6, 11, 0, 3, 47)
>>> time_offset = datetime.timedelta(hours=8)
>>> scan_time = original_time - time_offset
>>> scan_time.timestamp()
1402387427.0
- 如果只是把
scan_time
格式化为字符串,那确实看起来是正确的UTC日期时间。 - 而在时区是UTC+8的系统上,
scan_time.timestamp()
得到结果1402387427.0
,
再把这个时间戳转换成UTC日期时间,是2014-06-10 08:03:47
,比正确的UTC日期时间又少了8小时,这是错误的。
暂未得知其他使用了 datetime.datetime
的地方是否有类似的隐患
CyanideCN commented
欢迎pr
Anebrithien commented
关于这处的代码,我有一点疑问
Lines 155 to 158 in b2dc3c5
这里为什么是1970-01-01 的前一天呢?
如果是这样的话,datetime.datetime.utcfromtimestamp()
就需要减去1天才行了
示例:
>>> datetime.datetime(1969, 12, 31) + datetime.timedelta(days=23333) + datetime.timedelta(milliseconds=23132)
datetime.datetime(2033, 11, 18, 0, 0, 23, 132000)
>>> epoch_seconds = (datetime.timedelta(days=23333) + datetime.timedelta(milliseconds=23132)).total_seconds()
>>> epoch_seconds
2015971223.132
>>> datetime.datetime.utcfromtimestamp(epoch_seconds).replace(tzinfo=datetime.timezone.utc)
datetime.datetime(2033, 11, 19, 0, 0, 23, 132000, tzinfo=datetime.timezone.utc)
>>> datetime.datetime.utcfromtimestamp(epoch_seconds).replace(tzinfo=datetime.timezone.utc).timestamp()
2015971223.132
CyanideCN commented
关于这处的代码,我有一点疑问
Lines 155 to 158 in b2dc3c5
这里为什么是1970-01-01 的前一天呢? 如果是这样的话,
datetime.datetime.utcfromtimestamp()
就需要减去1天才行了示例:
>>> datetime.datetime(1969, 12, 31) + datetime.timedelta(days=23333) + datetime.timedelta(milliseconds=23132) datetime.datetime(2033, 11, 18, 0, 0, 23, 132000) >>> epoch_seconds = (datetime.timedelta(days=23333) + datetime.timedelta(milliseconds=23132)).total_seconds() >>> epoch_seconds 2015971223.132 >>> datetime.datetime.utcfromtimestamp(epoch_seconds).replace(tzinfo=datetime.timezone.utc) datetime.datetime(2033, 11, 19, 0, 0, 23, 132000, tzinfo=datetime.timezone.utc) >>> datetime.datetime.utcfromtimestamp(epoch_seconds).replace(tzinfo=datetime.timezone.utc).timestamp() 2015971223.132
这是当时写的时候试出来的,如果是按文档里的1970-01-01就会比实际上的日期多了一天,我也不知道为什么