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.

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.


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.


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)

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.


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.


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

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

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)

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.