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

В чем разница между 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)

5 ответов

Решение

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

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

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

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)

Одним из основных отличий, не выделенных в других ответах, является наличие существительных в единственном и множественном числе для каждого примитива разницы во времени. В то время как timedelta предлагает только существительные во множественном числе (например, hours, days) обозначить относительную разницу во времени, relativedelta предлагает также существительные в единственном числе (например, hour, day) для обозначения абсолютного времени информации.

Это ясно из определения 2 классов:

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только в несколько более запутанном виде.

Как упомянул @julien, на порядок быстрее, чем . Вот простая демонстрация с использованием дней:

      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(например, добавление дельты за неделю/месяц/год).

Согласно https://seihotech.com/comparing-datetime-timedelta-and-dateutil-relativedelta-relativedelta-in-python/

      datetime.timedelta 
  • функция из стандартной библиотеки Python
  • работает только с днями
      dateutil.relativedelta.relativedelta 
  • сторонний модуль
  • может работать с другими компонентами даты: например, часами, минутами и секундами.
Другие вопросы по тегам