PEP 500 – 用于将日期时间方法委托给其 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 - “日期时间方法委托协议”),可供 datetime.tzinfo 接口的具体实现使用,以覆盖感知型日期时间的算术、格式化和解析。我们描述了 datetime.datetime 类的更改,以支持新协议,并提出了一个新的抽象类 datetime.tzstrict,该类实现了此协议的部分必要功能,以使感知型日期时间实例遵循“严格”算术规则。
基本原理
截至 Python 3.5,共享 tzinfo 对象的感知型日期时间实例遵循由(年、月、日、小时、分钟、秒、微秒)7元组和大型整数之间的简单双射所引起的算术规则。在此算术中,YEAR-11-02T12:00 和 YEAR-11-01T12:00 之间的差值始终为 24 小时,尽管例如在美国/东部时区,2014-11-01T12:00 和 2014-11-02T12:00 之间有 25 小时,因为当地时钟在 2014-11-02T02:00 回拨了一小时,在 2014-11-01 和 2014-11-02 之间的夜晚增加了一小时。
许多业务应用程序要求使用 Python 对本地日期的简化视图。没有哪家自尊的租车公司会因为一周跨越夏令时结束而向客户收取比其他任何一周更多的费用,或者要求他们提前一小时还车。因此,改变当前感知型日期时间算术的规则不仅会造成向后兼容性噩梦,还会消除对合法且常见用例的支持。
由于不可能为当地时间算术选择通用规则,我们建议将这些规则的实现委托给实现 datetime.tzinfo 接口的类。通过这种委托,用户只需为 tzinfo 的值选择不同类的实例,即可选择不同的算术。
协议
日期时间相减
支持 PDDM 的 tzinfo 子类可以定义一个名为 __datetime_diff__ 的方法,该方法应接受两个 datetime.datetime 实例,并返回一个 datetime.timedelta 实例,表示从第一个日期时间实例所表示的时间到另一个日期时间实例所表示的时间之间经过的时间。
加法
支持 PDDM 的 tzinfo 子类可以定义一个名为 __datetime_add__ 的方法,该方法应接受两个参数——一个日期时间实例和一个时间差实例——并返回一个日期时间实例。
时间差相减
支持 PDDM 的 tzinfo 子类可以定义一个名为 __datetime_sub__ 的方法,该方法应接受两个参数——一个日期时间实例和一个时间差实例——并返回一个日期时间实例。
格式化
支持 PDDM 的 tzinfo 子类可以定义名为 __datetime_isoformat__ 和 __datetime_strftime__ 的方法。
方法 __datetime_isoformat__ 应接受一个日期时间实例和一个可选的分隔符,并生成给定日期时间实例的字符串表示。
方法 __datetime_strftime__ 应接受一个日期时间实例和一个格式字符串,并根据给定格式生成给定日期时间实例的字符串表示。
解析
支持 PDDM 的 tzinfo 子类可以定义一个名为 __datetime_strptime__ 的类方法,并将其实现的“规范”时区名称注册到一个注册表中。 TODO 描述注册表。
日期时间方法的更改
减法
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
加法
当 self.tzinfo.__datetime_add__ 方法被定义时,将时间差添加到日期时间实例的操作将委托给该方法。
严格算术
一个新的抽象 datetime.tzinfo 子类,名为 datetime.tzstrict,将被添加到 datetime 模块中。此子类将不实现 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)
解析和格式化
当 strftime 和 isoformat 日期时间方法被定义时,它们将委托给其 tzinfo 成员中同名的方法。
当 datetime.strptime 方法给定一个包含 %Z 指令的格式字符串时,它将根据给定的时区名称在注册表中查找 tzinfo 实现,并调用其 __datetime_strptime__ 方法。
应用
本 PEP 将支持第三方实现许多不同的计时方案,包括
- 儒略历 / Microsoft Excel 日历。
- 支持闰秒的“正确”时区。
- 法国革命历(需要大量工作)。
版权
本文档已置于公共领域。
来源:https://github.com/python/peps/blob/main/peps/pep-0500.rst