何时使用 datetime.utcnow() 或 datetime.now(tz=pytz.utc).replace(tzinfo=None)

When to use datetime.utcnow() or datetime.now(tz=pytz.utc).replace(tzinfo=None)

我想了解什么时候应该使用

datetime.now(tz=pytz.utc).replace(tzinfo=None)

而不是简单地

datetime.utcnow()

后者会不会考虑例如夏令时?

datetime.datetime 的很多工作方式取决于 运行 所在的机器。主机的本地时间和时区设置将决定您将获得的输出。

如果主机在 UTC 时区,则 datetime.datetime.now()datetime.datetime.utcnow() 之间没有区别。

根据 pytz documentation:

The preferred way of dealing with times is to always work in UTC, converting to localtime only when generating output to be read by humans.

pytz 用于计算夏令时,datetime.datetime.utcnow() 用于提供一个通用的标准化参考点,您可以根据该参考点计算夏令时。 datetime.datetime.utcnow() 它本身不会考虑夏令时。

你永远不应该使用 datetime.utcnow(),因为它给了你一个天真的时间戳,你可以用它来搬起石头砸自己的脚。如果你真的想要一个朴素的时间戳,请使用你的第一个选项使其明确。 now() 采用 tz 参数(您应该始终提供该参数,以避免使用主机 TZ)。但是 utcnow() 显然没有提供。所以注定了。

例如,假设您有一个 UTC 时间戳,并且您想将其转换为墨西哥城的当地时间:

my_timestamp.astimezone(pytz.timezone("America/Mexico_City"))

看起来不错吧?不,看看这个:

>>> datetime.utcnow()
datetime.datetime(2021, 3, 29, 21, 40, 44, 329559)
>>> datetime.utcnow().astimezone(pytz.timezone("America/Mexico_City"))
datetime.datetime(2021, 3, 29, 21, 40, 44, 329559, tzinfo=<DstTzInfo 'America/Mexico_City' CST-1 day, 18:00:00 STD>)

如您所见,如果您给它一个简单的时间戳,astimezone 只会添加 tz,而不会按预期调整实际时间。 (如果你不想调整,你会使用.replace

这非常令人困惑,如果您只是确保没有简单的时间戳,就不会 运行 遇到这样的问题。如果愿意,您可以将它们放在外部 API 中,但在它们进入系统时要加上时区。

总而言之:始终使用 datetime.now(tz=some_tz)

引用Paul Ganssle's article Stop using utcnow and utcfromtimestamp

[Don't] use utcnow() or utcfromtimestamp() simply because it's the wrong abstraction.

[...]

The reason that we cannot simply change utcnow() into an alias for now(timezone.utc) in the standard library is that would change the semantics of how those datetimes are treated by their consumers

IIRC,他在 datetime 附近为 cpython(Python 的核心)做出了相当大的贡献。

因此:不要使用 datetime.utcnow()