soustraire deux fois en python

117

J'ai deux datetime.timevaleurs, exitet enterje veux faire quelque chose comme:

duration = exit - enter

Cependant, j'obtiens cette erreur:

TypeError: type (s) d'opérande non pris en charge pour -: 'datetime.time' et 'datetime.time

Comment faire cela correctement? Une solution possible est de convertir les timevariables en datetimevariables, puis de les soustraire, mais je suis sûr que vous devez avoir un moyen meilleur et plus propre.

Chaggster
la source

Réponses:

91

Essaye ça:

from datetime import datetime, date

datetime.combine(date.today(), exit) - datetime.combine(date.today(), enter)

combine construit un datetime, qui peut être soustrait.

gruszczy
la source
2
Pour @ IgnacioVazquez-Abrams, on pourrait utiliser, par exemple, à la datetime(1,1,1,0,0,0)place de date.today().
Akavall
25
Ne nommez pas a datetime exit, car exitc'est une fonction intégrée.
orokusaki
1
en utilisant python 2.7, je n'ai pas de combineméthode dans mon datetimemodule: AttributeError: 'module' object has no attribute 'combine'
mtoloo
6
mtoloo: Il y a un datetimemodule et il a un datetimeobjet à l'intérieur. L'objet à l'intérieur a une combineméthode. Si vous importez simplement datetime(comme ceci :) import datetime, alors ce que vous devez faire plus tard est ceci datetime.datetime.combine.
gruszczy
1
Il existe un cas très rare lorsque vous appelez cette fonction à un moment comme 23: 59: 59: 9999. Dans ce cas, l' date.today() avant et le date.today()plus tard renverront une valeur différente. Il serait préférable de donner la valeur date.today()à une variable.
ramwin
44

Utilisation:

from datetime import datetime, date

duration = datetime.combine(date.min, end) - datetime.combine(date.min, beginning)

L'utilisation date.minest un peu plus concise et fonctionne même à minuit.

Cela pourrait ne pas être le cas avec date.today()cela pourrait renvoyer des résultats inattendus si le premier appel se produit à 23:59:59 et le suivant à 00:00:00.

alexpirine
la source
1
D'accord avec toi.
ramwin
27

au lieu d'utiliser le temps, essayez timedelta:

from datetime import timedelta

t1 = timedelta(hours=7, minutes=36)
t2 = timedelta(hours=11, minutes=32)
t3 = timedelta(hours=13, minutes=7)
t4 = timedelta(hours=21, minutes=0)

arrival = t2 - t1
lunch = (t3 - t2 - timedelta(hours=1))
departure = t4 - t3

print(arrival, lunch, departure)
Edmilson Junior
la source
2
Merci. C'est très propre et meilleur que toutes les réponses ici - stackoverflow.com/questions/3096953/…
Pushpak Dagade
7

datetime.timene prend pas en charge cela, car il est presque inutile de soustraire des temps de cette manière. Utilisez un plein datetime.datetimesi vous voulez faire cela.

Ignacio Vazquez-Abrams
la source
53
Si vous savez de votre domaine que deux datetime.timeobjets aet bsont du même jour, et cela b > a, alors l'opération b - aa un sens parfait.
swalog
4
Même s'ils ne sont pas le même jour, cela a toujours un bon sens. Au moins autant de sens que arctan(0) = (0, pi, 2pi, ...), mais nous ne nous soucions simplement d'aucune de ces valeurs après la première. Alors, 4:00 - 20:00est 8:00- il est aussi ( 32:00, 56:00, ...), mais qui se soucie?
naught101
7
De plus, Python ne reste même pas cohérent. Si a - b n'a pas de sens pour deux objets temporels, alors comment se comporte a> b ou a <b? La comparaison suppose déjà le même jour, sinon elle est complètement cassée. Puisque l'hypothèse est faite à des fins de comparaison, il est tout à fait cohérent de faire la même hypothèse pour les opérations de différence.
Sean
1
Dire que cela n'a pas de sens est subjectif, mais je vois d'où vous venez. Ajouter deux fois ensemble me semble être une représentation dénuée de sens. Je pense que la soustraction de deux valeurs de temps devrait renvoyer un timedelta. Si ce délai est négatif, qu'il en soit ainsi. Ce que je veux savoir, c'est pourquoi python ne peut pas ajouter ou soustraire un chronomètre d'une heure pour renvoyer une nouvelle valeur de temps.
aj.toulan
7

Vous avez deux objets datetime.time donc pour cela vous créez simplement deux timedelta en utilisant datetime.timedetla puis soustrayez comme vous le faites maintenant en utilisant l'opérande "-". Voici un exemple de façon de soustraire deux fois sans utiliser datetime.

enter = datetime.time(hour=1)  # Example enter time
exit = datetime.time(hour=2)  # Example start time
enter_delta = datetime.timedelta(hours=enter.hour, minutes=enter.minute, seconds=enter.second)
exit_delta = datetime.timedelta(hours=exit.hour, minutes=exit.minute, seconds=exit.second)
difference_delta = exit_delta - enter_delta

difference_delta est votre différence que vous pouvez utiliser pour vos raisons.

Hardik Patel
la source
Il est possible de reconvertir l'objet timedelta en datetime? Je veux dire que nous avons difference_delta .seconds (), y a-t-il un moyen de récupérer un objet datetime ou time? Thx
dejdej
Oui. datetime.min + delta
sourcedelica
6

La bibliothèque python timedelta devrait faire ce dont vous avez besoin. A timedeltaest renvoyé lorsque vous soustrayez deux datetimeinstances.

import datetime
dt_started = datetime.datetime.utcnow()

# do some stuff

dt_ended = datetime.datetime.utcnow()
print((dt_ended - dt_started).total_seconds())
Ben
la source
4
import datetime

def diff_times_in_seconds(t1, t2):
    # caveat emptor - assumes t1 & t2 are python times, on the same day and t2 is after t1
    h1, m1, s1 = t1.hour, t1.minute, t1.second
    h2, m2, s2 = t2.hour, t2.minute, t2.second
    t1_secs = s1 + 60 * (m1 + 60*h1)
    t2_secs = s2 + 60 * (m2 + 60*h2)
    return( t2_secs - t1_secs)

# using it
diff_times_in_seconds( datetime.datetime.strptime( "13:23:34", '%H:%M:%S').time(),datetime.datetime.strptime( "14:02:39", '%H:%M:%S').time())
Jacanterbury
la source
3

datetime.time ne peut pas le faire - mais vous pourriez utiliser datetime.datetime.now()

start = datetime.datetime.now()
sleep(10)
end = datetime.datetime.now()
duration = end - start
gies0r
la source
2

J'ai eu une situation similaire à celle que vous et moi avons fini par utiliser une bibliothèque externe appelée arrow .

Voici à quoi cela ressemble:

>>> import arrow
>>> enter = arrow.get('12:30:45', 'HH:mm:ss')
>>> exit = arrow.now()
>>> duration = exit - enter
>>> duration
datetime.timedelta(736225, 14377, 757451)
rominf
la source
1
Ici, vous ne faites que démontrer la soustraction d'objets datetime complets, pas d'heures de la journée comme dans la question d'origine
kleptog