В чем разница между "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
(например, добавление дельты за неделю/месяц/год).
datetime.timedelta
- функция из стандартной библиотеки Python
- работает только с днями
dateutil.relativedelta.relativedelta
- сторонний модуль
- может работать с другими компонентами даты: например, часами, минутами и секундами.