为什么 datetime.utcnow().timestamp() 在相同环境和终端下,Python 和 IPython 返回不同的值

问题描述 投票:0回答:1

在 IPython 中:

Python 3.6.2 (default, Sep  4 2017, 13:34:02) 
Type 'copyright', 'credits' or 'license' for more information
IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: datetime.utcnow().timestamp()
Out[1]: 1515396403.049774

在Python中:

Python 3.6.2 (default, Sep  4 2017, 13:34:02) 
[GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.42)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> datetime.utcnow().timestamp()
1515425220.215077
>>> 

IPython 的结果似乎位于我的时区而不是 UTC。

编辑:如果不调用

.timestamp()
,则
.utcnow()
返回的值在两个终端中是相同的。为什么会这样?

编辑2:

在常规 Python 提示符中,

datetime.utcnow().timestamp()
datetime.utcnow().replace(tzinfo=timezone.utc).timestamp()
的值不同。

Python 3.6.2 (default, Sep  4 2017, 13:34:02) 
[GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.42)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from datetime import datetime, timezone
>>> datetime.utcnow().replace(tzinfo=timezone.utc).timestamp()
1515548420.130655
>>> datetime.utcnow().timestamp()
1515577235.982597

在 IPython 中,这些值是相同的。

编辑3:

在 IPython 上

now
utcnow
返回相同的结果。在 Python 中,
now
返回我的当地时间。

In [4]: datetime.utcnow()
Out[4]: datetime.datetime(2018, 1, 10, 1, 44, 55, 496083)

In [5]: datetime.now()
Out[5]: datetime.datetime(2018, 1, 10, 1, 45, 53, 811077)

Python:

>>> datetime.datetime.now()
datetime.datetime(2018, 1, 9, 17, 46, 29, 754642)
>>> datetime.datetime.utcnow()
datetime.datetime(2018, 1, 10, 1, 46, 32, 865136)
python datetime ipython utc
1个回答
0
投票

当在

datetime.timestamp()
的时区朴素实例上调用
datetime
时,它假定该值是本地日期时间。因此,永远不应该使用代码
datetime.utcnow().timestamp()
,因为非本地时区天真
datetime.utcnow()
违反了该假设。

获取 UTC 时间戳的“旧”正确方法是:

datetime.now().timestamp()

更好的方法是使用时区感知版本来避免天真的日期时间:

datetime.now(tz=timezone.utc).timestamp()

查看效果的一个相当简单的方法是在时区偏移非零的环境中使用以下代码:

from datetime import datetime, timezone
now1 = datetime.now()
now2 = datetime.utcnow()
now3 = datetime.now(tz=timezone.utc)
now1
now1.timestamp()
now2
now2.timestamp()
now3
now3.timestamp()

这会产生如下输出:

>>> from datetime import datetime, timezone
>>> now1 = datetime.now()
>>> now2 = datetime.utcnow()
>>> now3 = datetime.now(tz=timezone.utc)
>>> now1
datetime.datetime(2023, 12, 16, 11, 50, 0, 979519)
>>> now1.timestamp()
1702749000.979519
>>> now2
datetime.datetime(2023, 12, 16, 17, 50, 0, 982995)
>>> now2.timestamp()
1702770600.982995
>>> now3
datetime.datetime(2023, 12, 16, 17, 50, 0, 983405, tzinfo=datetime.timezone.utc)
>>> now3.timestamp()
1702749000.983405

如上所示,当使用“旧”方式与时区原生本地日期时间

now1
时,
timestamp()
应用时区偏移量,从而产生 UTC 时间戳值。同样,使用时区感知
now3
日期时间
timestamp()
的“更好”方式。产生相同的结果。但是,由于在调用
now2
utcnow()
已经应用了一次时区偏移,因此在 timezone-naive 值上调用
timestamp()
第二次应用时区偏移,从而产生已应用时区偏移的时间戳值两次!在上面的示例中,时区位于 UTC 以西 6 小时,导致时间戳实际上比当地时间早 12 小时,因此错误地比 UTC 提前 6 小时。

© www.soinside.com 2019 - 2024. All rights reserved.