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

Roi*_*bes 4 python datetime utc

很确定这是一件容易的事,但我不明白。

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

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

当我这样做时,fromtimestamp我得到了正确的 utc 小时,但是当我使用时,utcfromtimestamp我得到了另外 3 小时的偏移。

不过,文档要求我使用fromtimestamp本地时区和utcfromtimestamputc 用法。

我缺少什么?这两个函数的初始假设是时间戳是在本地时区中给出的吗?

谢谢 :)

MrF*_*pes 5

同时使用 datetime 对象及其 POSIX 时间戳(Unix 时间)时要注意的关键一点是,Python 假定原始 datetime 对象(没有时区信息的对象)引用本地时间(操作系统设置)。相反,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
Run Code Online (Sandbox Code Playgroud)

我希望这能澄清,如果您调用datetime.utcfromtimestamp(ts_utcnow),您将获得双倍的本地时间 UTC 偏移量。Python 假设(我认为这是相当理智的)时间戳指的是 UTC - 事实上,它不是。

我的建议是使用时区感知的日期时间对象;喜欢datetime.now(tz=timezone.utc)。如果您正在处理时区,dateutil库或 Python 3.9 的zoneinfo模块非常有帮助。如果您想深入挖掘,请查看datetime src 代码