sottrarre due volte in python


117

Ho due datetime.timevalori, exited entere voglio fare qualcosa di simile:

duration = exit - enter

Tuttavia, ottengo questo errore:

TypeError: tipi di operandi non supportati per -: 'datetime.time' e 'datetime.time

Come posso farlo correttamente? Una possibile soluzione è convertire le timevariabili in datetimevariabili e poi sottrarle, ma sono sicuro che voi ragazzi dovete avere un modo migliore e più pulito.

Risposte:


91

Prova questo:

from datetime import datetime, date

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

combine costruisce un datetime, che può essere sottratto.


2
Per il punto @ IgnacioVazquez-Abrams, si potrebbe usare, diciamo, datetime(1,1,1,0,0,0)invece di date.today().
Akavall

25
Non nominare un datetime exit, poiché exitè una funzione incorporata.
orokusaki

1
usando python 2.7, non ho un combinemetodo nel mio datetimemodulo: AttributeError: 'module' object has no attribute 'combine'
mtoloo

6
mtoloo: C'è un datetimemodulo e ha un datetimeoggetto all'interno. L'oggetto all'interno ha un combinemetodo. Se stai semplicemente importando datetime(in questo modo :) import datetime, ciò che devi fare in seguito è questo datetime.datetime.combine.
gruszczy

1
C'è un caso molto raro quando chiami questa funzione in un momento come 23: 59: 59: 9999. In tal caso, il date.today() prima e il date.today()dopo restituiranno un valore diverso. Sarebbe meglio dare il valore date.today()a una variabile.
ramwin

44

Uso:

from datetime import datetime, date

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

L'utilizzo date.minè un po 'più conciso e funziona anche a mezzanotte.

Questo potrebbe non essere il caso, date.today()che potrebbe restituire risultati imprevisti se la prima chiamata avviene alle 23:59:59 e la successiva alle 00:00:00.


1
Sono d'accordo con te.
ramwin

27

invece di usare il tempo prova 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)

2
Grazie. Questo è molto pulito e meglio di tutti le risposte qui - stackoverflow.com/questions/3096953/...
Pushpak Dagade

7

datetime.timenon lo supporta, perché non ha quasi senso sottrarre i tempi in questo modo. Usa un full datetime.datetimese vuoi farlo.


53
Se sai dal tuo dominio che due datetime.timeoggetti ae bsono dello stesso giorno, e questo b > a, allora l'operazione b - aha un significato perfetto.
Swalog

4
Anche se non sono lo stesso giorno, ha comunque senso. Almeno tanto senso quanto arctan(0) = (0, pi, 2pi, ...), ma non ci interessa nessuno di quei valori dopo il primo. Quindi, 4:00 - 20:00è 8:00- è anche ( 32:00, 56:00, ...), ma che importa?
nought101


7
Inoltre, Python non rimane nemmeno coerente. Se a - b non ha significato per due oggetti temporali, allora come si comporta che a> b o a <b si comporta in questo modo? Il confronto è già ipotizzato lo stesso giorno, altrimenti è completamente rotto. Poiché l'ipotesi è fatta per il confronto, è del tutto coerente fare la stessa ipotesi per operazioni di differenza.
Sean

1
Dire che non ha senso è soggettivo, ma capisco da dove vieni. L'aggiunta di due volte insieme sembra essere una rappresentazione priva di significato per me. Penso che sottraendo due valori di tempo dovrebbe restituire un timedelta. Se quel timedelta sembra essere negativo, così sia. Quello che voglio sapere è perché python non può aggiungere o sottrarre un timedelta da un tempo per restituire un nuovo valore di tempo.
aj.toulan

7

Hai due oggetti datetime.time quindi crei solo due timedelta usando datetime.timedetla e poi sottrai come fai adesso usando l'operando "-". Di seguito è riportato il modo di esempio per sottrarre due volte senza utilizzare 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

Differenza_delta è la tua differenza che puoi usare per le tue ragioni.


È possibile riconvertire l'oggetto timedelta in datetime? Voglio dire, abbiamo difference_delta .seconds (), c'è un modo per recuperare un oggetto datetime o time? Thx
dejdej

Sì. datetime.min + delta
sourcedelica

6

La libreria Python timedelta dovrebbe fare quello che ti serve. A timedeltaviene restituito quando sottrai due datetimeistanze.

import datetime
dt_started = datetime.datetime.utcnow()

# do some stuff

dt_ended = datetime.datetime.utcnow()
print((dt_ended - dt_started).total_seconds())

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

3

datetime.time non puoi farlo - Ma potresti usare datetime.datetime.now()

start = datetime.datetime.now()
sleep(10)
end = datetime.datetime.now()
duration = end - start

2

Ho avuto una situazione simile quando io e te abbiamo finito con l'utilizzo di una libreria esterna chiamata freccia .

Ecco come appare:

>>> import arrow
>>> enter = arrow.get('12:30:45', 'HH:mm:ss')
>>> exit = arrow.now()
>>> duration = exit - enter
>>> duration
datetime.timedelta(736225, 14377, 757451)

1
Qui stai solo dimostrando la sottrazione di oggetti datetime completi, non le ore del giorno come nella domanda originale
kleptog
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.