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

2024-10-01 17:39:37 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图做一些Pythondatetimedelta数学,偶然发现了这一点。在

>>> 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

到目前为止还不错,但是当timedelta还包括一些小时时,它就变得有趣了。在

^{pr2}$

或者比较一下:

>>> dt - td == dt + (-td)
False

我本以为a-b==a+(-b),但这对日期timedelta似乎不起作用。就我所能追踪到的,这是因为加/减datetimedelta只考虑了timedelta的days字段,这可能是正确的。然而,否定atimedelta会考虑所有字段,也可能会更改days字段。在

>>> -datetime.timedelta(days=1)
datetime.timedelta(-1)
>>> -datetime.timedelta(days=1, hours=1)
datetime.timedelta(-2, 82800)

从第二个例子中可以看出,在否定之后days=-2,因此date+timedelta实际上将减去2天。在

这应该被认为是pythondatetime模块中的一个bug吗?或者这是某种“正常”的行为,在做这种事情时需要考虑到?在

在内部,datetime模块创建了一个新的timedelta,只传递了原始timedelta对象的days字段。这相当于下面的代码看起来很奇怪。在

>>> dt + datetime.timedelta(-(-(-dt).days))
datetime.date(2000, 4, 18)

我真的不知道为什么在做日期-时间增量减法时只使用否定的days字段。在

编辑:

以下是pythondatetime模块中的相关代码路径:

class date:

    ...

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

如果它只传递给-other,那么条件a-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
        ...

Tags: 模块代码selfdatetimedatedefdtdays
2条回答

这是因为负数timedelta的表示方式。在

import datetime
td = datetime.timedelta(days=1, hours=1)
print (td.days, td.seconds)
# prints 1 3600
minus_td = -td
print (minus_td.days, minus_td.seconds)
# prints -2 82800

我希望你现在能更好地理解为什么days受到影响。在

timedelta中的秒数始终规范化为0到86399之间的正值:

^{pr2}$

Should this be considered a bug in the python datetime module? Or is this rather some 'normal' behaviour which needs to be taken into account when doing things like that?

不,这不应该被认为是一个bug。date不会以小时、分钟和秒来跟踪其状态,这是它按照您建议的方式运行所需的。在

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

相关问题 更多 >

    热门问题