仅处理天数时,“datetime.timedelta”和“dateutil.relativedelta.relativedelta”之间有什么区别?

问题描述 投票:0回答:5

仅使用天数时,

datetime.timedelta
(来自 Python 标准库)和
dateutil.relativedelta.relativedelta
有什么区别?

据我了解,

timedelta
仅支持天(和周),而
relativedelta
增加了对以年、月、周或日定义的时间段的支持,以及定义年、月或日的绝对值。 (请记住,就这个问题而言,我不必担心小时、分钟或秒)

考虑到我只处理

datetime.date
对象,并且只对由天数定义的周期感兴趣,
timedelta
relativedelta
之间有什么区别?有什么区别吗?

from datetime import date, timedelta
from dateutil.relativedelta import relativedelta

i = -1  # This could have been any integer, positive or negative
someday = date.today()
# Is there any difference between these two lines?
otherday = someday + timedelta(days=i)
otherday = someday + relativedelta(days=i)
python datetime timedelta
5个回答
111
投票

dateutil
是Python标准
datetime
模块的扩展包。正如您所说,它提供了额外的功能,例如以大于一天的单位表示的时间增量。

如果您必须问一些问题,例如在我女朋友的生日到来之前我可以节省多少个月,或者该月的最后一个星期五是哪一天?这隐藏了由于月份长度不同或闰年额外天数引起的复杂计算。

就您而言,您只对天数感兴趣。因此,您最好使用

timedelta
,因为这可以避免对
dateutil
包的额外依赖。


60
投票

A

relativedelta
timedelta
具有更多参数:

Definition:   relativedelta.relativedelta(self, dt1=None, dt2=None,
years=0, months=0, days=0, leapdays=0, weeks=0, hours=0, minutes=0,
seconds=0, microseconds=0, year=None, month=None, day=None,
weekday=None, yearday=None, nlyearday=None, hour=None, minute=None,
second=None, microsecond=None)

你可以用它来做一些事情,比如计算一个月的最后一个星期五:

In [14]: import datetime as dt

In [15]: import dateutil.relativedelta as relativedelta

In [16]: today = dt.date.today()

In [17]: rd = relativedelta.relativedelta(day = 31, weekday = relativedelta.FR(-1))

In [18]: today+rd
Out[18]: datetime.date(2012, 9, 28)

26
投票

其他答案中未突出显示的一个主要区别是每个时差原语都存在单数和复数名词。虽然

timedelta
仅提供复数名词(例如
hours
days
)来表示相对时间差,
relativedelta
也提供单数名词(例如
hour
day
)来表示绝对时间信息。

这从这两个类的定义中可以清楚地看出:

Definition:   datetime.timedelta([days[, seconds[, microseconds[, 
milliseconds[, minutes[, hours[, weeks]]]]]]])

Definition:   relativedelta.relativedelta(self, dt1=None, dt2=None,
years=0, months=0, days=0, leapdays=0, weeks=0, hours=0, minutes=0,
seconds=0, microseconds=0, year=None, month=None, day=None,
weekday=None, yearday=None, nlyearday=None, hour=None, minute=None,
second=None, microsecond=None)

现在,单数形式到底有什么作用?单数形式创建一个增量,当添加到

datetime
对象时,将
datetime
对象中的特定日期/时间基元设置为
relativedelta
中提到的日期/时间基元。这是一个小例子:

>>> import datetime as dt; from dateutil.relativedelta import *
>>> NOW = dt.datetime(2018, 11, 17, 9, 6, 31)
>>> NOW
datetime.datetime(2018, 11, 17, 9, 6, 31)
>>> NOW + relativedelta(hours=1) #Simply add one hour
datetime.datetime(2018, 11, 17, 10, 6, 31)
>>> NOW + relativedelta(hour=1) #Set the hour to 01:00 am
datetime.datetime(2018, 11, 17, 1, 6, 31)

这可能会导致

relativedelta
被用于一些有趣的应用程序,而使用
timedelta
来实现这些应用程序可能会很复杂。很快我想到的是四舍五入。

一个有趣的应用:快速四舍五入

我现在将向您展示

relativedelta
在将
datetime
对象四舍五入到最接近的分钟、小时、天等时如何更具表现力。

四舍五入到最接近的小时:

注意使用

relativedelta
进行四舍五入是多么简单:

#Using `relativedelta`
NOW + relativedelta(hours=1, minute=0, second=0, microsecond=0)

#Using `timedelta`
dt.combine(NOW.date(),dt.time(NOW.hour,0,0)) + dt.timedelta(0,60*60,0)

使用

relativedelta
可以轻松实现其他更复杂的舍入。但是,请注意,可以通过
relativedelta
完成的所有舍入也可以使用
datetime
函数和
timedelta
完成,只是方式稍微复杂一些。


2
投票

正如 @julien 提到的,

timedelta
relativedelta
快一个数量级。这是使用天数的简单演示:

In [1]: from datetime import date, timedelta
   ...: from dateutil.relativedelta import *
   ...: import timeit

In [2]: def td():
   ...:     return date.today() + timedelta(days=7)
   ...:

In [3]: def rd():
   ...:     return date.today() + relativedelta(days=7)
   ...:

In [4]: timeit.timeit('td()', 'from __main__ import td', number=1000)
Out[4]: 0.0019557802006602287

In [5]: timeit.timeit('rd()', 'from __main__ import rd', number=1000)
Out[5]: 0.014670956879854202

如果性能很重要,则应避免使用

relativedelta
,除非使用
timedelta
无法完成任务(例如添加周/月/年增量)。


0
投票

根据https://seihotech.com/comparing-datetime-timedelta-and-dateutil-relativedelta-relativedelta-in-python/

datetime.timedelta 
  • Python 标准库中的函数
  • 仅适用于天数
dateutil.relativedelta.relativedelta 
  • 第三方模块
  • 可以与其他日期组件一起使用:例如:小时、分钟和秒
© www.soinside.com 2019 - 2024. All rights reserved.