6

请谨慎使用 datetime.utcnow()

 3 years ago
source link: https://segmentfault.com/a/1190000040374683
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

请谨慎使用 datetime.utcnow()

执行下面代码:

import time
from datetime import datetime, timezone, timedelta

print(time.time())
print(datetime.utcnow().timestamp())
print(datetime.now(timezone.utc).timestamp())
print(datetime.now(timezone(timedelta(hours=2))).timestamp())

==== output ====
1626687759.9081082
1626658959.908108
1626687759.908108
1626687759.908108

发现,输出的时间戳中只有 utcnow() 是不一样,如果对比相差的时间能发现正好差8小时,而我电脑所在的时区正好是东八区。

正如 utcnow() 文档 所表明的那样,它返回的是 naive time ,Naive datetime 实例被认为为表示本地时间,因此它的时间戳会比使用 now(None) 相差的时间正好是该电脑所在时区。

造成这种诡异处理方式的是有历史原因的,在 Python 2 转 Python 3 的过渡阶段中,datetime.timezone 作为 3.2 版中的新功能被设计了出来,因此有了更为清晰明确的标记日期所在的时区。旧的接口 utcnow() 则保留了原先的处理方式。

新的时区的模型的处理方式与Python 2 存在兼容问题:

==== Python 2 ====
>>> from datetime import datetime
>>> from dateutil import tz
>>> datetime(2021, 5, 1).astimezone(tz.UTC)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: astimezone() cannot be applied to a naive datetime

==== Python 3 ====
>>> from datetime import datetime
>>> from dateutil import tz
>>> datetime(2021, 5, 1).astimezone(tz.UTC)
datetime.datetime(2021, 5, 1, 4, 0, tzinfo=tzutc())

综上所述, utcnow() 可能是一个常见的陷阱。我建议不要再使用 utcnow()utcfromtimestamp()


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK