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()
。在您的示例中,发生了不太明显的事情:
datetime.now().timestamp()
- now() 为您提供了一个类似于本地时间的原始日期时间对象。如果您调用 timestamp(),Python 会将日期时间转换为 UTC 并为其计算时间戳。
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.
很确定这很简单,但我不明白。
我当地的 TZ 目前是 GMT+3,当我从 datetime.utcnow().timestamp()
获取时间戳时,它确实比 datetime.now().timestamp()
在我的流程中的另一个过程中,我使用了那个 utc 时间戳并需要将其转换为日期时间。
当我做 fromtimestamp
时,我得到正确的 utc 小时,但是当我使用 utcfromtimestamp
时,我得到另一个 3 小时的偏移量。
不过,文档要求我对本地时区使用 fromtimestamp
,对 utc 用法使用 utcfromtimestamp
。
我错过了什么?两个函数的初始假设是时间戳是在本地时区给出的吗?
谢谢:)
同时使用日期时间对象及其 POSIX 时间戳(Unix 时间)时要注意的关键是原始日期时间对象(没有时区信息的对象)由 Python 参考本地时间(OS 设置)。相反,POSIX 时间戳(应该)总是指自纪元 UTC 以来的秒数。你可以明确地获得那个,例如来自 time.time()
。在您的示例中,发生了不太明显的事情:
datetime.now().timestamp()
- now() 为您提供了一个类似于本地时间的原始日期时间对象。如果您调用 timestamp(),Python 会将日期时间转换为 UTC 并为其计算时间戳。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.