行为是
documented:
date2 is moved forward in time if timedelta.days > 0, or backward if timedelta.days < 0. Afterward date2 - date1 == timedelta.days. timedelta.seconds and timedelta.microseconds are ignored.
(我的强调,这个行为有remained unchanged,因为Python 2.3中添加了日期对象。)
我没有找到任何证据表明为什么模块是这样设计的。当然,有一些使用案例,比如你想要代表一天开始的午夜时间点。在这种情况下,不得不来回转换是令人厌烦的。但是还有其他用例要代表一整天(而不是当天的某个时间点),在这种情况下,您不希望在添加timedeltas时意外地结束部分日子。
克里斯·威瑟斯(Chris Withers)建议在issue 3249改变行为,但蒂姆·彼得斯指出:
an incompatible change to documented always-worked-this-way behavior is unlikely to be accepted.
如果你想要一个像datetime.date一样的对象,但是如果算术运算返回datetime.datetime对象,那么编写一个对象不应该太难:
from datetime import date, datetime, time, timedelta
def _part_day(t):
"""Return True if t is a timedelta object that does not consist of
whole days.
"""
return isinstance(t, timedelta) and (t.seconds or t.microseconds)
class mydate(date):
"""Subclass of datetime.date where arithmetic operations with a
timedelta object return a datetime.datetime object unless the
timedelta object consists of whole days.
"""
def datetime(self):
"""Return datetime corresponding to the midnight at start of this
date.
"""
return datetime.combine(self, time())
def __add__(self, other):
if _part_day(other):
return self.datetime() + other
else:
return super().__add__(other)
__radd__ = __add__
def __sub__(self, other):
if _part_day(other):
return self.datetime() - other
else:
return super().__sub__(other)
(这是未经测试的,但这不是很难让它从这里工作。)