datetime.now(tz=pytz.utc).replace(tzinfo=None)
与简单地相反
datetime.utcnow()
后者不会考虑夏令时等因素吗?
datetime.datetime
的许多工作方式取决于它运行的计算机。主机机器的本地时间和时区设置将决定您将获得的输出。
如果主机机器在UTC时区,则datetime.datetime.now()
和datetime.datetime.utcnow()
之间没有区别。
根据pytz文档:
处理时间的首选方法是始终使用UTC,仅在生成供人类阅读的输出时转换为本地时间。
pytz
用于考虑夏令时,而datetime.datetime.utcnow()
用于提供一个通用的标准参考点,以便您可以计算夏令时。仅使用datetime.datetime.utcnow()
无法考虑夏令时。
引用Paul Ganssle的文章Stop using utcnow and utcfromtimestamp
[不要]使用utcnow()或utcfromtimestamp(),因为这是错误的抽象。
[...]
我们不能简单地将utcnow()更改为标准库中now(timezone.utc)的别名,原因在于这会改变那些日期时间对象在其消费者中被处理的语义
我记得他在Python的核心cpython(即Python解释器)的datetime模块中做出了相当大的贡献。
因此:不要使用datetime.utcnow()
使用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)
。