我只是偶然发现
>>> a = datetime.datetime(2017, 12, 24)
>>> b = datetime.datetime(2017, 12, 24, tzinfo=datetime.timezone.utc)
>>> a - b
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't subtract offset-naive and offset-aware datetimes
现在我想知道:为什么没有所有日期时间对象一个时区?时区是否大于 UTC 的偏移量(+关联名称)?
因为时区不是平凡的,而不仅仅是简单的偏移量,而且并非所有用例都需要考虑时区。
不是简单的偏移
时区通常不仅仅是与 UTC 的偏移量。例如,时区还可以规定夏令时(时区在夏令时和冬令时之间切换的确切时间)。
并非所有用例都需要处理 DST,有时您具有仅包含与 UTC 的偏移量的日期时间值的字符串表示形式。但这并不意味着您可以假设时区处理通常只需要处理偏移量。
时区不是静态实体
时区也会随时间而变化;哪些物理位置使用确切的时区可以更改,以及时区的规则。因为地球很大,这种情况发生的频率比你想象的要高。不仅 DST 规则或地理范围会发生变化,时区偏移也会发生变化。 有关历史时区更改的示例,请参阅 Jon Skeet 的最高投票答案,其中数据库条目也随着时间的推移而得到更正。
这样的变化肯定比Python版本更频繁地发生。因此,Python 无法随标准库一起发布全面的时区数据库,并希望它在下一个版本之前保持最新状态。相反,Python 维护者依靠第三方库来生成这样的数据库;这样的库可以遵循更激进的发布周期。
并非所有用例都需要时区
但是,许多涉及日期时间计算的用例不需要包含时区;它们可以而且应该与时区无关。无论如何,强制所有此类用例使用时区都会给开发人员带来不必要的负担,然后他们必须了解如何使用包含时区信息的其他日期时间值处理计算。
因此,datetime
库区分没有时区的"简单"日期时间值和具有时区的日期时间值。在 Python 3.2 之前,该库甚至不包含timezone
对象;这留给了第三方图书馆。当前的datetime.timezone()
支持是为了支持没有历史记录或 DST 支持的简单偏移时区;这些至少不需要不断的维护和更新。
如果您需要访问正确的时区
时区的规范Python实现是pytz
包,它打包了Olson数据库(由类UNIX操作系统使用,包括Mac OS X)。每当 Olson 数据库更新时,都会创建一个新版本;我希望新的 2018-01 版本来打包最近的 2018c 版本。
请注意,datetime
库设计预计不必处理pytz
包含时区的历史时区更改;请遵循pytz
文档并使用timezone.localize(naive_datetime)
为日期应用正确的偏移量。请参阅如何在 python 中使无法识别的日期时间时区
python-dateutil
包还包含时区支持。