Quelle est la différence entre «datetime.timedelta» et «dateutil.relativedelta.relativedelta» lorsque vous travaillez uniquement avec des jours?

90

Quelle est la différence entre datetime.timedelta(à partir de la bibliothèque standard de Python) et dateutil.relativedelta.relativedeltalorsque vous travaillez uniquement avec des jours?

Pour autant que je sache, timedeltane prend en charge que les jours (et les semaines), tout en relativedeltaajoutant un support pour des périodes définies en termes d'années, de mois, de semaines ou de jours, ainsi que la définition de valeurs absolues pour l'année, le mois ou le jour. (rappelez-vous, pour les besoins de cette question, je n'ai pas à me soucier des heures, des minutes ou des secondes)

Étant donné que je ne travaille qu'avec des datetime.dateobjets et que je ne m'intéresse qu'aux périodes définies par le nombre de jours, quelle est la différence entre timedeltaet relativedelta? Y a-t-il une différence?

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
la source
3
Si vous n'êtes intéressé que par les deltas dans les jours entre les dates, utilisez simplement la bibliothèque standard dateime.timedeltaqui permettra d'obtenir ce que vous voulez et d'éviter la dépendance au dateutilpaquet externe .
Pedro Romano le
Il vaut la peine de dire qu'en plus d'économiser une dépendance supplémentaire, le calcul des deltas en jours entre les dates est plusieurs fois plus rapide avec timedelta qu'avec relativedelta. (~ 10 fois)
Julien B.10

Réponses:

76

dateutilest un package d'extension du datetimemodule standard python . Comme vous le dites, il fournit des fonctionnalités supplémentaires, telles que les timedeltas qui sont exprimées en unités supérieures à un jour.

Ceci est utile si vous devez poser des questions telles que combien de mois puis-je économiser avant l'anniversaire de ma petite amie, ou quel est le dernier vendredi du mois? Cela masque les calculs complexes causés par les différentes longueurs des mois ou les jours supplémentaires dans les années bissextiles.

Dans votre cas, vous n'êtes intéressé que par le nombre de jours. Il vaut donc mieux l'utiliser timedeltacar cela évite une dépendance supplémentaire sur le dateutilpackage.

Hans alors
la source
32

A relativedeltaa beaucoup plus de paramètres qu'un 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)

avec lequel vous pouvez faire des choses comme calculer le dernier vendredi d'un mois:

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
la source
1
C'est une réponse fantastique qui a donné un nouvel aperçu de l'utilisation d'un relativedelta pour des choses comme "dernier vendredi du mois" :) Merci!
PascalVKooten
10

Une différence majeure non soulignée dans les autres réponses est la présence de noms singuliers et pluriels pour chaque primitive de différence de temps. Bien timedeltaque n'offre que des noms au pluriel (par exemple hours, days) pour désigner une différence de temps relative, relativedeltaoffre également des noms au singulier (par exemple hour, day) pour désigner des informations de temps absolues.

Cela ressort clairement de la définition des 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)

Maintenant, que fait exactement la forme singulière? La forme singulière crée un delta qui, lorsqu'il est ajouté à un datetimeobjet, définit cette primitive de date / heure spécifique dans l' datetimeobjet sur celle mentionnée dans le relativedelta. Voici un petit exemple:

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

Cela peut conduire à relativedeltaêtre utilisé pour certaines applications intéressantes, qui peuvent être compliquées à mettre en œuvre timedelta. Une solution qui me vient rapidement à l'esprit est l'arrondissement.

Une application intéressante: arrondir rapidement

Je vais maintenant vous montrer comment il relativedeltaest plus expressif d'arrondir un datetimeobjet à la minute, à l'heure, au jour, etc.

Arrondir à l'heure la plus proche:

Remarquez à quel point il est simple d'arrondir en utilisant 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)

D'autres arrondis plus compliqués sont facilement réalisables en utilisant relativedelta. Cependant, notez que tous les arrondis qui peuvent être effectués par relativedeltapeuvent également être effectués à l'aide de datetimefonctions et timedelta, seulement de manière légèrement plus alambiquée.

shivams
la source