В чем разница между datetime.timedelta и dateutil.relativedelta.relativedelta при работе только с днями?

90

В чем разница между 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)
Денилсон Са Майя
источник
3
Если вас интересуют только дельты в днях между датами, просто используйте стандартную библиотеку, dateime.timedeltaкоторая позволит достичь желаемого и избежать зависимости от внешнего dateutilпакета.
Педро Романо
Стоит сказать, что помимо сохранения одной дополнительной зависимости, вычисление дельт в днях между датами в несколько раз быстрее с timedelta, чем с relativedelta. (~ 10 раз)
Жюльен Б.

Ответы:

76

dateutil- это пакет расширения для стандартного datetimeмодуля Python . Как вы говорите, он предоставляет дополнительные функции, такие как timedeltas, выраженные в единицах, превышающих день.

Это полезно, если вам нужно задать вопросы, например, сколько месяцев я могу сэкономить до дня рождения моей девушки или какая последняя пятница в месяце? Это скрывает сложные вычисления, которые вызваны разной длиной месяцев или лишними днями в високосных годах.

В вашем случае вас интересует только количество дней. Так что вам лучше использовать, так timedeltaкак это позволяет избежать дополнительной зависимости от dateutilпакета.

Ганс Тогда
источник
32

У A relativedeltaнамного больше параметров, чем у a 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)
Unutbu
источник
1
Это фантастический ответ, который дал новое понимание использования relativedelta для таких вещей, как «последняя пятница месяца» :) Спасибо!
PascalVKooten 04
10

Одно из основных различий, не освещенное в других ответах, - это наличие существительных в единственном и множественном числе для каждого примитива разницы во времени. Хотя 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)

Итак, что именно делает форма единственного числа? Форма Singular создает дельту, которая при добавлении к 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, только немного более запутанным способом.

шивамы
источник