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

python: utcfromtimestamp vs fromtimestamp, when the timestamp is based on utcnow()

很确定这很简单,但我不明白。

我当地的 TZ 目前是 GMT+3,当我从 datetime.utcnow().timestamp() 获取时间戳时,它确实比 datetime.now().timestamp()

少了 3 小时

在我的流程中的另一个过程中,我使用了那个 utc 时间戳并需要将其转换为日期时间。

当我做 fromtimestamp 时,我得到正确的 utc 小时,但是当我使用 utcfromtimestamp 时,我得到另一个 3 小时的偏移量。

不过,文档要求我对本地时区使用 fromtimestamp,对 utc 用法使用 utcfromtimestamp

我错过了什么?两个函数的初始假设是时间戳是在本地时区给出的吗?

谢谢:)

同时使用日期时间对象及其 POSIX 时间戳(Unix 时间)时要注意的关键是原始日期时间对象(没有时区信息的对象)由 Python 参考本地时间(OS 设置)。相反,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.now(tz=timezone.utc)。如果您使用时区,dateutil library or Python 3.9's zoneinfo module are very helpful. And if you want to dig deep, have a look at the datetime src code.