Python:utcfromtimestamp vs fromtimestamp,当时间戳基于utcnow()时

4
我很确定这是一个简单的问题,但我不太明白。
我的本地时区当前为GMT+3,当我从datetime.utcnow().timestamp()获取时间戳时,确实比datetime.now().timestamp()少了3小时。
在流程的另一个过程中,我需要将该utc时间戳转换为日期时间。
当我使用fromtimestamp时,我得到正确的utc小时数,但当我使用utcfromtimestamp时,我会再次得到3小时的偏移量。
然而,文档要求我在本地时区使用fromtimestamp,在utc使用utcfromtimestamp
我缺少什么? 这两个函数的初始假设都是时间戳以本地时区形式给出吗?
谢谢 :)

相关链接:https://dev59.com/wbvoa4cB1Zd3GeqPzTQV - FObersteiner
1个回答

5
当处理日期时间对象和它们的POSIX时间戳(Unix时间)时,需要注意一个关键问题,即Python假定没有时区信息的原始日期时间对象(没有时区信息的对象)是指本地时间(操作系统设置)。相比之下,POSIX时间戳(应该)始终指的是自纪元UTC以来的秒数。您可以从time.time()中明确获得这一点。在您的示例中,会发生不太明显的事情:
  1. datetime.now().timestamp() - now()会给您提供类似于本地时间的原始日期时间对象。如果调用timestamp(),Python将转换为UTC并计算出该时间戳。

  2. datetime.utcnow().timestamp() - utcnow()会给您提供类似于UTC的原始日期时间对象。但是,如果调用timestamp(),Python会假定(由于原始)该日期时间是本地时间,并再次转换为UTC,然后计算时间戳!因此,所得到的时间戳与UTC相差两倍于本地时间的UTC偏移量。

这里有一个代码示例。让我们创建一些时间戳。请注意,我在UTC+2(CEST),偏移量为-7200秒。

import time
from datetime import datetime, timezone

ts_ref = time.time() # reference POSIX timestamp

ts_utcnow = datetime.utcnow().timestamp() # dt obj UTC but naive - so also assumed local

ts_now = datetime.now().timestamp() # dt obj naive, assumed local

ts_loc_utc = datetime.now(tz=timezone.utc).timestamp() # dt obj localized to UTC

print(int(ts_utcnow - ts_ref))
# -7200 # -> ts_utcnow doesn't refer to UTC!
print(int(ts_now - ts_ref))
# 0 # -> correct
print(int(ts_loc_utc - ts_ref))
# 0 # -> correct

我希望这样可以解释清楚,如果您调用datetime.utcfromtimestamp(ts_utcnow),您会得到本地时间UTC偏移量的两倍。Python默认(我认为很明智)时间戳是指UTC时间 - 实际上并不是。我的建议是使用时区感知的datetime对象;比如datetime.now(tz=timezone.utc)。如果您正在使用时区,dateutil库或Python 3.9的zoneinfo模块非常有用。如果您想深入了解,可以查看datetime源代码

1
我终于懂了,讲解得很清楚。非常感谢! - Roie Labes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接