PEP 500 – 将 datetime 方法委托给其 tzinfo 实现的协议
- 作者:
- Alexander Belopolsky <alexander.belopolsky at gmail.com>,Tim Peters <tim.peters at gmail.com>
- 讨论邮件列表:
- Datetime-SIG 邮件列表
- 状态:
- 已拒绝
- 类型:
- 标准跟踪
- 依赖:
- 495
- 创建日期:
- 2015年8月8日
- 决议:
- Datetime-SIG 邮件
摘要
本 PEP 指定了一个新的协议(PDDM - “将日期时间方法委托给其 tzinfo 实现的协议”),可供 datetime.tzinfo
接口的具体实现用于覆盖感知日期时间的算术运算、格式化和解析。我们描述了对 datetime.datetime
类的更改以支持新协议,并提出一个新的抽象类 datetime.tzstrict
,该类实现了使感知日期时间实例遵循“严格”算术规则所需的部分协议。
基本原理
从 Python 3.5 开始,共享 tzinfo
对象的感知日期时间实例遵循由 (year, month, day, hour, minute, second, microsecond) 7 元组与大整数之间简单双射引起的算术规则。在这种算术运算中,YEAR-11-02T12:00 和 YEAR-11-01T12:00 之间的差值始终为 24 小时,即使在 US/Eastern 时区中,例如,2014-11-01T12:00 和 2014-11-02T12:00 之间有 25 小时,因为本地时钟在 2014-11-02T02:00 回拨了一小时,在 2014-11-01 和 2014-11-02 之间的夜晚增加了一个小时。
许多商业应用程序需要使用 Python 对本地日期的简化视图。任何有尊严的租车公司都不会因为跨越夏令时结束的一周而向客户收取更多费用,也不会要求他们提前一小时还车。因此,更改感知日期时间算术的当前规则不仅会造成向后兼容性问题,还会消除对合法且常见用例的支持。
由于无法为本地时间算术选择通用规则,因此我们建议将这些规则的实现委托给实现 datetime.tzinfo
接口的类。有了这样的委托,用户只需选择不同类的实例作为 tzinfo
的值,即可在不同的算术运算之间进行选择。
协议
datetime的减法
支持 PDDM 的 tzinfo
子类可以定义一个名为 __datetime_diff__
的方法,该方法应接受两个 datetime.datetime
实例并返回一个 datetime.timedelta
实例,表示从第一个 datetime 实例表示的时间到另一个时间经过的时间。
加法
支持 PDDM 的 tzinfo
子类可以定义一个名为 __datetime_add__
的方法,该方法应接受两个参数——一个 datetime 实例和一个 timedelta 实例——并返回一个 datetime 实例。
timedelta的减法
支持 PDDM 的 tzinfo
子类可以定义一个名为 __datetime_sub__
的方法,该方法应接受两个参数——一个 datetime 实例和一个 timedelta 实例——并返回一个 datetime 实例。
格式化
支持 PDDM 的 tzinfo
子类可以定义名为 __datetime_isoformat__
和 __datetime_strftime__
的方法。
__datetime_isoformat__
方法应接受一个 datetime 实例和一个可选的分隔符,并生成给定 datetime 实例的字符串表示形式。
__datetime_strftime__
方法应接受一个 datetime 实例和一个格式字符串,并生成给定 datetime 实例的字符串表示形式,该字符串根据给定的格式进行格式化。
解析
支持 PDDM 的 tzinfo
子类可以定义一个名为 __datetime_strptime__
的类方法,并在注册表中注册其实现的时区的“规范”名称。**待办事项** 描述注册表。
对 datetime 方法的更改
减法
class datetime:
def __sub__(self, other):
if isinstance(other, datetime):
try:
self_diff = self.tzinfo.__datetime_diff__
except AttributeError:
self_diff = None
try:
other_diff = self.tzinfo.__datetime_diff__
except AttributeError:
other_diff = None
if self_diff is not None:
if self_diff is not other_diff and self_diff.__func__ is not other_diff.__func__:
raise ValueError("Cannot find difference of two datetimes with "
"different tzinfo.__datetime_diff__ implementations.")
return self_diff(self, other)
elif isinstance(other, timedelta):
try:
sub = self.tzinfo.__datetime_sub__
except AttributeError:
pass
else:
return sub(self, other)
return self + -other
else:
return NotImplemented
# current implementation
加法
将 timedelta 添加到 datetime 实例将委托给 self.tzinfo.__datetime_add__
方法(只要该方法已定义)。
严格算术
将向 datetime
模块添加一个名为 datetime.tzstrict
的 datetime.tzinfo
类的新抽象子类。此子类不会实现 utcoffset()
、tzname()
或 dst()
方法,但会实现 PDDM 的一些方法。
tzstrict
实现的 PDDM 方法将等效于以下内容
class tzstrict(tzinfo):
def __datetime_diff__(self, dt1, dt2):
utc_dt1 = dt1.astimezone(timezone.utc)
utc_dt2 = dt2.astimezone(timezone.utc)
return utc_dt2 - utc_dt1
def __datetime_add__(self, dt, delta):
utc_dt = dt.astimezone(timezone.utc)
return (utc_dt + delta).astimezone(self)
def __datetime_sub__(self, dt, delta):
utc_dt = dt.astimezone(timezone.utc)
return (utc_dt - delta).astimezone(self)
解析和格式化
Datetime 方法 strftime
和 isoformat
将委托给其 tzinfo
成员的同名方法(只要这些方法已定义)。
当 datetime.strptime
方法获得包含 %Z
指令的格式字符串时,它将通过给定的时区名称在注册表中查找 tzinfo
实现,并调用其 __datetime_strptime__
方法。
应用
此 PEP 将使第三方能够实现许多不同的时间保存方案,包括
- 儒略历/Microsoft Excel 日历。
- 支持闰秒的“正确”时区。
- 法国革命历法(需要大量工作)。
版权
本文档已置于公共领域。
来源:https://github.com/python/peps/blob/main/peps/pep-0500.rst
上次修改时间:2023年9月9日17:39:29 GMT