Python日期和时间减法的惊人行为

gwe*_*eis 7 python date timedelta

我正在尝试做一些Python 日期timedelta数学,并偶然发现了这一点.

>>> import datetime
>>> dt = datetime.date(2000, 4, 20)
>>> td = datetime.timedelta(days=1)
>>> dt - td
datetime.date(2000, 4, 19)
>>> -(td) + dt
datetime.date(2000, 4, 19)
>>> dt - td == dt + (-td)
True
Run Code Online (Sandbox Code Playgroud)

到目前为止一切都那么好,但是当timedelta还包括几个小时它会变得有趣.

>>> td = datetime.timedelta(days=1, hours=1)
>>> dt - td
datetime.date(2000, 4, 19)
>>> -(td) + dt
datetime.date(2000, 4, 18)
Run Code Online (Sandbox Code Playgroud)

或者在比较中:

>>> dt - td == dt + (-td)
False
Run Code Online (Sandbox Code Playgroud)

我本来期望a - b == a +( - b),但这似乎不适用于日期时间.至于我能跟踪下来,这是因为加/减日期timedelta只考虑天领域timedelta,这可能是正确的.但是,否定timedelta会考虑所有字段,也可能会更改days字段.

>>> -datetime.timedelta(days=1)
datetime.timedelta(-1)
>>> -datetime.timedelta(days=1, hours=1)
datetime.timedelta(-2, 82800)
Run Code Online (Sandbox Code Playgroud)

从第二个例子中可以看出,在否定之后天数= -2,因此日期+时间δ实际上将减去2天.

这应该被认为是python datetime模块中的错误吗?或者这是一些"正常"的行为,在做这样的事情时需要加以考虑?

在内部,日期时间模块创建一个新的timedelta,只有原来的日子领域timedelta减去时传入,对象timedelta约会对象.这相当于以下,代码似乎很奇怪.

>>> dt + datetime.timedelta(-(-(-dt).days))
datetime.date(2000, 4, 18)
Run Code Online (Sandbox Code Playgroud)

在做date - timedelta减法时,我无法真正想到使用否定的日期字段.

编辑:

这是python datetime模块中的相关代码路径:

class date:

    ...

    def __sub__(self, other):
        """Subtract two dates, or a date and a timedelta."""
        if isinstance(other, timedelta):
           return self + timedelta(-other.days)
        ...
Run Code Online (Sandbox Code Playgroud)

如果它只是传递-other则条件一个- B == A +(-B)将成立.(它会改变目前的行为).

class date:

    ...

    def __sub__(self, other):
        """Subtract two dates, or a date and a timedelta."""
        if isinstance(other, timedelta):
           return self - other  # timedelta.__rsub__ would take care of negating other
        ...
Run Code Online (Sandbox Code Playgroud)

Jon*_*sky 2

这应该被视为 python datetime 模块中的错误吗?或者这是一些在做类似事情时需要考虑的“正常”行为?

不,这不应被视为错误。Adate不会按照小时、分钟和秒来跟踪其状态,而这是它按照您建议的方式运行所需要的。

我认为您提供的代码是一个错误:程序员在他们试图完成的工作中使用了错误的数据类型。如果你想以天、小时、分钟和秒为单位记录时间,那么你需要一个datetime对象。date(一旦你完成了所有你想做的算术,它会很乐意为你提供一个)