Qual é a diferença entre “datetime.timedelta” e “dateutil.relativedelta.relativedelta” ao trabalhar apenas com dias?

91

Qual é a diferença entre datetime.timedelta(da biblioteca padrão do Python) e dateutil.relativedelta.relativedeltaao trabalhar apenas com dias?

Pelo que entendi, timedeltasó suporta dias (e semanas), enquanto relativedeltaadiciona suporte para períodos definidos em termos de anos, meses, semanas ou dias, além de definir valores absolutos para ano, mês ou dia. (lembre-se, para o propósito desta pergunta, não preciso me preocupar com horas, minutos ou segundos)

Considerando que trabalho apenas com datetime.dateobjetos, e apenas interessado em períodos definidos pelo número de dias, qual a diferença entre timedeltae relativedelta? Existe alguma diferença?

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)
Denilson Sá Maia
fonte
3
Se você está interessado apenas em deltas em dias entre datas, basta usar a biblioteca padrão dateime.timedeltaque vai conseguir o que você deseja e evitar a dependência do dateutilpacote externo .
Pedro Romano
Vale a pena dizer que, além de salvar uma dependência extra, calcular deltas em dias entre as datas é várias vezes mais rápido com timedelta do que relativedelta. (~ 10 vezes)
Julien B.

Respostas:

77

dateutilé um pacote de extensão para o datetimemódulo padrão python . Como você disse, ele fornece funcionalidade extra, como timedeltas que são expressos em unidades maiores que um dia.

Isso é útil se você tiver que fazer perguntas como quantos meses posso economizar antes do aniversário da minha namorada ou qual é a última sexta-feira do mês? Isso oculta cálculos complexos causados ​​por diferentes durações dos meses ou dias extras em anos bissextos.

No seu caso, você está interessado apenas no número de dias. Portanto, é melhor usar, timedeltapois isso evita uma dependência extra do dateutilpacote.

Hans então
fonte
33

A relativedeltatem muito mais parâmetros do que 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)

com o qual você pode fazer coisas como calcular a última sexta-feira em um mês:

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
fonte
1
Esta é uma resposta fantástica que deu uma nova visão de como usar um relativedelta para coisas como "última sexta-feira do mês" :) Obrigado!
PascalVKooten
12

Uma diferença importante não destacada em outras respostas é a presença de substantivos no singular e no plural para cada diferença de tempo primitiva. Embora timedeltaapenas ofereça substantivos no plural (por exemplo hours, days) para denotar a diferença de tempo relativa, relativedeltaoferece também substantivos no singular (por exemplo hour, day) para denotar informações de tempo absoluto.

Isso fica claro na definição das 2 classes:

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)

Agora, exatamente o que a forma singular faz? A forma singular cria um delta que, quando adicionado a um datetimeobjeto, define aquela data / hora primitiva específica no datetimeobjeto para aquela mencionada no relativedelta. Aqui está um pequeno exemplo:

>>> 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)

Isso pode levar ao relativedeltauso para alguns aplicativos interessantes, que podem ser complicados de implementar usando timedelta. Um que vem rapidamente à mente é o arredondamento.

Um aplicativo interessante: arredondamento rápido

Vou agora mostrar como relativedeltaé mais expressivo ao arredondar um datetimeobjeto para o minuto, hora, dia mais próximo, etc.

Arredondando para a hora mais próxima:

Observe como é fácil arredondar usando 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)

Outros arredondamentos mais complicados são facilmente alcançáveis ​​usando relativedelta. No entanto, note que todos os arredondamentos que podem ser feitos por relativedeltatambém podem ser feitos por meio de datetimefunções e timedelta, apenas de uma forma um pouco mais complicada.

shivams
fonte