odejmij dwa razy w Pythonie

117

Mam dwie datetime.timewartości, exita enteri chcę zrobić coś takiego:

duration = exit - enter

Jednak pojawia się ten błąd:

TypeError: nieobsługiwane typy operandów dla -: 'datetime.time' i 'datetime.time

Jak mam to zrobić poprawnie? Jednym z możliwych rozwiązań jest konwersja timezmiennych na datetimezmienne, a następnie subtruct, ale jestem pewien, że musicie mieć lepszy i czystszy sposób.

Chaggster
źródło

Odpowiedzi:

91

Spróbuj tego:

from datetime import datetime, date

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

combine tworzy datę i godzinę, którą można odjąć.

gruszczy
źródło
2
Do punktu @ IgnacioVazquez-Abrams można by użyć, powiedzmy, datetime(1,1,1,0,0,0)zamiast date.today().
Akavall,
25
Nie nazywaj nazwy datetime exit, ponieważ exitjest to funkcja wbudowana.
orokusaki
1
używając Pythona 2.7, nie mam combinemetody w moim datetimemodule: AttributeError: 'module' object has no attribute 'combine'
mtoloo
6
mtoloo: Jest datetimemoduł i ma datetimewewnątrz obiekt. Obiekt wewnątrz ma combinemetodę. Jeśli po prostu importujesz datetime(w ten sposób import datetime:), to co musisz zrobić później, to to datetime.datetime.combine.
gruszczy
1
Jest bardzo rzadki przypadek, gdy wywołujesz tę funkcję w pewnym momencie, np. 23: 59: 59: 9999. W takim przypadku date.today() poprzednie i date.today()późniejsze zwrócą inną wartość. Lepiej byłoby nadać wartość date.today()zmiennej.
ramwin
44

Posługiwać się:

from datetime import datetime, date

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

Używanie date.minjest nieco bardziej zwięzłe i działa nawet o północy.

Może się tak nie zdarzyć, date.today()ponieważ może to zwrócić nieoczekiwane wyniki, jeśli pierwsze połączenie nastąpi o 23:59:59, a następne o 00:00:00.

alekspiryna
źródło
1
Zgadzam się z Tobą.
ramwin
27

zamiast używać czasu, spróbuj 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
źródło
2
Dzięki. To jest bardzo
przejrzyste
7

datetime.timenie obsługuje tego, ponieważ odejmowanie czasów w ten sposób jest prawie bez znaczenia. Użyj pełnego, datetime.datetimejeśli chcesz to zrobić.

Ignacio Vazquez-Abrams
źródło
53
Jeśli znasz z domeny że dwa datetime.timeobiekty ai bsą z tego samego dnia, a które b > a, wówczas operacja b - ama doskonały sens.
swalog,
4
Nawet jeśli nie są tego samego dnia, nadal ma to sens. Przynajmniej tak samo sensownie, jak arctan(0) = (0, pi, 2pi, ...), ale nie przejmujemy się żadną z tych wartości po pierwszej. Tak, 4:00 - 20:00jest 8:00- to również ( 32:00, 56:00...), ale kogo to obchodzi?
naught101
7
Co więcej, Python nie jest nawet spójny. Jeśli a - b jest bez znaczenia dla dwóch obiektów czasu, to jak zachowuje się a> b lub a <b? Porównanie zakłada już ten sam dzień, inaczej jest całkowicie zepsute. Ponieważ założenie to jest zrobione dla porównania, całkowicie spójne jest przyjmowanie tego samego założenia dla operacji różnicowych.
Sean
1
Mówienie, że to bez znaczenia jest subiektywne, ale widzę, skąd pochodzisz. Dodanie dwóch razy do siebie wydaje mi się bezsensowną reprezentacją. Myślę, że odjęcie dwóch wartości czasu powinno zwrócić timedelta. Jeśli ten timedelta okaże się negatywny, niech tak będzie. Chcę wiedzieć, dlaczego Python nie może dodawać ani odejmować timedelta od czasu, aby zwrócić nową wartość czasu.
aj.toulan
7

Masz dwa obiekty datetime.time, więc wystarczy utworzyć dwie timedelta za pomocą datetime.timedetla, a następnie odjąć, tak jak teraz, używając operandu „-”. Oto przykładowy sposób odejmowania dwukrotności bez użycia daty i godziny.

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

różnica_delta to różnica, której możesz użyć ze swoich powodów.

Hardik Patel
źródło
Czy jest możliwe przekonwertowanie obiektu timedelta z powrotem na datę i godzinę? Chodzi mi o to, że mamy Difference_delta .seconds (), czy istnieje sposób na odzyskanie obiektu daty i godziny? Thx
dejdej
Tak. datetime.min + delta
sourcedelica
6

Biblioteka timedelta Pythona powinna zrobić to, czego potrzebujesz. A timedeltajest zwracane po odjęciu dwóch datetimewystąpień.

import datetime
dt_started = datetime.datetime.utcnow()

# do some stuff

dt_ended = datetime.datetime.utcnow()
print((dt_ended - dt_started).total_seconds())
Ben
źródło
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
źródło
3

datetime.time nie mogę tego zrobić - ale możesz użyć datetime.datetime.now()

start = datetime.datetime.now()
sleep(10)
end = datetime.datetime.now()
duration = end - start
gies0r
źródło
2

Miałem podobną sytuację jak ty i ja skończyliśmy na korzystaniu z zewnętrznej biblioteki o nazwie arrow .

Oto jak to wygląda:

>>> import arrow
>>> enter = arrow.get('12:30:45', 'HH:mm:ss')
>>> exit = arrow.now()
>>> duration = exit - enter
>>> duration
datetime.timedelta(736225, 14377, 757451)
rominf
źródło
1
Tutaj po prostu demonstrujesz odejmowanie całych obiektów daty i godziny, a nie pory dnia, jak w pierwotnym pytaniu
kleptog