Яка різниця між “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 . Як ви кажете, він надає додаткові функціональні можливості, такі як таймельти, які виражаються в одиницях, більших за день.

Це корисно, якщо вам доводиться задавати питання, наприклад, скільки місяців я можу заощадити до настання дня народження моєї дівчини, або яка остання п’ятниця місяця? Це приховує складні розрахунки, спричинені різною тривалістю місяців або додатковими днями у високосному році.

У вашому випадку вас цікавить лише кількість днів. Отже, найкраще використовувати, 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)

1
Це фантастична відповідь, яка дала нове розуміння використання відносної дельти для таких речей, як "остання п'ятниця місяця" :) Дякую!
PascalVKooten

10

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.