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

24
我想要了解何时应该使用什么。
datetime.now(tz=pytz.utc).replace(tzinfo=None)

与简单地相反

datetime.utcnow()

后者不会考虑夏令时等因素吗?

4个回答

19

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

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

根据pytz文档

处理时间的首选方法是始终使用UTC,仅在生成供人类阅读的输出时转换为本地时间。

pytz用于考虑夏令时,而datetime.datetime.utcnow()用于提供一个通用的标准参考点,以便您可以计算夏令时。仅使用datetime.datetime.utcnow()无法考虑夏令时。


6

引用Paul Ganssle的文章Stop using utcnow and utcfromtimestamp

[不要]使用utcnow()或utcfromtimestamp(),因为这是错误的抽象。

[...]

我们不能简单地将utcnow()更改为标准库中now(timezone.utc)的别名,原因在于这会改变那些日期时间对象在其消费者中被处理的语义

我记得他在Python的核心cpython(即Python解释器)的datetime模块中做出了相当大的贡献。

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


6

使用datetime.utcnow()方法会得到一个天真的时间戳,可能会给自己带来麻烦,因此不建议使用。如果确实需要一个天真的时间戳,请使用第一个选项显式地创建它。 now()方法接受tz参数(你应该总是提供这个参数以避免使用主机TZ)。但是utcnow()方法显然没有提供tz参数,因此它注定要失败。

例如,假设你有一个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 只会在给出一个无时区的时间戳时附加上时区信息,并且不会像预期的那样调整实际时间。(如果您不想进行调整,您应该使用 .replace)。

这非常令人困惑,如果您确保没有无时区的时间戳,就不会遇到这样的问题。如果您喜欢,在您的外部 API 中可以使用它们,但在它们进入系统时请添加时区信息。

总结一下:始终使用 datetime.now(tz=some_tz)


datetime.datetime.utcnow() datetime.datetime(2022, 10, 28, 14, 20, 36, 193346) datetime.datetime.utcnow().astimezone(pytz.timezone("America/Mexico_City")) datetime.datetime(2022, 10, 28, 9, 21, 10, 49778, tzinfo=<DstTzInfo 'America/Mexico_City' CDT-1 day, 19:00:00 DST>)
- AVI
它对我进行了调整。 - AVI
@AVI,我无法重现这个问题,请问你使用的是哪个版本的Python和pytz? - Janus Troelsen

0
这已经在Python 3.12中更新了,你应该只使用datetime.datetime.now(datetime.timezone.utc)。在datetime下面看到这里
请注意,datetime.utcnow()已被弃用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接