subtraia duas vezes em python

117

Eu tenho dois datetime.timevalores, exiteenter e quero fazer algo como:

duration = exit - enter

No entanto, recebo este erro:

TypeError: tipo (s) de operando não suportado (s) para -: 'datetime.time' e 'datetime.time

Como faço isso corretamente? Uma solução possível é converter as timevariáveis ​​em datetimevariáveis ​​e depois subtruir, mas tenho certeza de que vocês devem ter uma maneira melhor e mais limpa.

Chaggster
fonte

Respostas:

91

Experimente isto:

from datetime import datetime, date

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

combine constrói um datetime, que pode ser subtraído.

gruszczy
fonte
2
Para @IgnacioVazquez-Abrams apontar, pode-se usar, digamos, em datetime(1,1,1,0,0,0)vez de date.today().
Akavall,
25
Não nomeie um datetime exit, pois exité uma função embutida.
orokusaki
1
usando o python 2.7, não tenho combinemétodo em meu datetimemódulo: AttributeError: 'module' object has no attribute 'combine'
mtoloo
6
mtoloo: Existe um datetimemódulo e um datetimeobjeto dentro. O objeto dentro tem combinemétodo. Se você estiver simplesmente importando datetime(como este import datetime:), o que você precisa fazer mais tarde é isso datetime.datetime.combine.
gruszczy
1
Há um caso muito raro em que você chama essa função em algum momento como 23: 59: 59: 9999. Nesse caso, o date.today() antes e o date.today()depois retornarão um valor diferente. Seria melhor atribuir o valor date.today()a uma variável.
ramwin
44

Usar:

from datetime import datetime, date

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

O uso date.miné um pouco mais conciso e funciona até à meia-noite.

Pode não ser o caso, date.today()pois pode retornar resultados inesperados se a primeira chamada acontecer às 23:59:59 e a próxima às 00:00:00.

alexpirina
fonte
1
Concordo com você.
ramwin
27

em vez de usar o tempo, tente 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
fonte
2
Obrigado. Isso é muito
claro
7

datetime.timenão suporta isso, porque é quase sem sentido subtrair tempos dessa maneira. Use um completo datetime.datetimese quiser fazer isso.

Ignacio Vazquez-Abrams
fonte
53
Se você souber de seu domínio que dois datetime.timeobjetos ae bsão do mesmo dia, e isso b > a, a operação b - atem um significado perfeito.
swalog
4
Mesmo que não sejam no mesmo dia, ainda faz sentido. Pelo menos tanto sentido quanto arctan(0) = (0, pi, 2pi, ...), mas simplesmente não nos importamos com nenhum desses valores depois do primeiro. Então, 4:00 - 20:00é 8:00- é também ( 32:00, 56:00...), mas quem se importa?
naught101
7
Além disso, o Python nem mesmo permanece consistente. Se a - b não tem sentido para dois objetos de tempo, então como é que a> b ou a <b se comporta dessa forma? A comparação já está assumindo o mesmo dia, caso contrário, está completamente quebrada. Uma vez que a suposição é feita para comparação, é inteiramente consistente fazer a mesma suposição para operações de diferença.
Sean
1
Dizer que não tem sentido é subjetivo, mas vejo de onde você está vindo. Somar duas vezes parece ser uma representação sem sentido para mim. Acho que subtrair dois valores de tempo deve retornar um timedelta. Se esse timedelta for negativo, que seja. O que eu quero saber é por que o python não pode adicionar ou subtrair um timedelta de um tempo para retornar um novo valor de tempo.
aj.toulan
7

Você tem dois objetos datetime.time, portanto, basta criar dois timedelta usando datetime.timedetla e subtrair como faria agora usando o operando "-". A seguir está o exemplo de maneira de subtrair duas vezes sem usar 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

diferença_delta é a sua diferença que você pode usar para suas razões.

Hardik Patel
fonte
É possível converter o objeto timedelta de volta para datetime? Quer dizer, temos diferença_delta .segundos (), há alguma maneira de obter de volta um objeto datetime ou time? Thx
dejdej
Sim. datetime.min + delta
sourcedelica de
6

A biblioteca python timedelta deve fazer o que você precisa. A timedeltaé retornado quando você subtrai duas datetimeinstâncias.

import datetime
dt_started = datetime.datetime.utcnow()

# do some stuff

dt_ended = datetime.datetime.utcnow()
print((dt_ended - dt_started).total_seconds())
Ben
fonte
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
fonte
3

datetime.time não posso fazer isso - mas você poderia usar datetime.datetime.now()

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

Tive situação semelhante à de você e acabamos usando uma biblioteca externa chamada arrow .

Aqui está o que parece:

>>> import arrow
>>> enter = arrow.get('12:30:45', 'HH:mm:ss')
>>> exit = arrow.now()
>>> duration = exit - enter
>>> duration
datetime.timedelta(736225, 14377, 757451)
rominf
fonte
1
Aqui, você está apenas demonstrando a subtração de objetos datetime completos, não horários do dia como na pergunta original
kleptog de