restar dos veces en python

117

Tengo dos datetime.timevalores, exity entery quiero hacer algo como:

duration = exit - enter

Sin embargo, obtengo este error:

TypeError: tipos de operandos no admitidos para -: 'datetime.time' y 'datetime.time

¿Cómo hago esto correctamente? Una posible solución es convertir las timevariables en datetimevariables y luego subestructurar, pero estoy seguro de que ustedes deben tener una forma mejor y más limpia.

Chaggster
fuente

Respuestas:

91

Prueba esto:

from datetime import datetime, date

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

combine construye una fecha y hora, que se puede restar.

gruszczy
fuente
2
Para @ IgnacioVazquez-Abrams, se podría usar, digamos, en datetime(1,1,1,0,0,0)lugar de date.today().
Akavall
25
No nombre a datetime exit, ya que exites una función incorporada.
orokusaki
1
usando Python 2.7, no tengo un combinemétodo en mi datetimemódulo: AttributeError: 'module' object has no attribute 'combine'
mtoloo
6
mtoloo: Hay un datetimemódulo y tiene un datetimeobjeto dentro. El objeto dentro tiene combinemétodo. Si simplemente está importando datetime(así :) import datetime, lo que debe hacer más adelante es esto datetime.datetime.combine.
gruszczy
1
Hay un caso muy raro en el que se llama a esta función en algún momento como 23: 59: 59: 9999. En ese caso, date.today() antes y date.today()después devolverán un valor diferente. Sería mejor darle el valor date.today()a una variable.
ramwin
44

Utilizar:

from datetime import datetime, date

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

El uso date.mines un poco más conciso y funciona incluso a medianoche.

Este podría no ser el caso, ya date.today()que podría devolver resultados inesperados si la primera llamada ocurre a las 23:59:59 y la siguiente a las 00:00:00.

alexpirina
fuente
1
De acuerdo con usted.
ramwin
27

en lugar de usar el tiempo, intente 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
fuente
2
Gracias. Esto es muy limpio y mejor que todas las respuestas aquí - stackoverflow.com/questions/3096953/…
Pushpak Dagade
7

datetime.timeno admite esto, porque no tiene sentido restar tiempos de esta manera. Utilice un completo datetime.datetimesi desea hacer esto.

Ignacio Vázquez-Abrams
fuente
53
Si sabe por su dominio que dos datetime.timeobjetos ay bson del mismo día, y eso b > a, entonces la operación b - atiene un significado perfecto.
swalog
4
Incluso si no son el mismo día, tiene mucho sentido. Al menos tanto sentido como arctan(0) = (0, pi, 2pi, ...), pero simplemente no nos importa ninguno de esos valores después del primero. Por lo tanto, 4:00 - 20:00es 8:00- es también ( 32:00, 56:00, ...), pero a quién le importa?
naught101
7
Además, Python ni siquiera se mantiene constante. Si a - b no tiene sentido para dos objetos de tiempo, ¿cómo es que a> bo a <b se comporta como lo hace? La comparación ya está asumiendo el mismo día, de lo contrario está completamente rota. Dado que la suposición se hace para la comparación, es completamente consistente hacer la misma suposición para las operaciones de diferencia.
Sean
1
Decir que no tiene sentido es subjetivo, pero veo de dónde vienes. Sumar dos tiempos juntos me parece una representación sin sentido. Creo que restar dos valores de tiempo debería devolver un timedelta. Si ese timedelta resulta ser negativo, que así sea. Lo que quiero saber es por qué Python no puede sumar o restar un timedelta de un tiempo para devolver un nuevo valor de tiempo.
aj.toulan
7

Tiene dos objetos datetime.time, por lo que solo crea dos timedelta usando datetime.timedetla y luego reste como lo hace ahora usando el operando "-". A continuación se muestra la forma de ejemplo de restar dos veces sin 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

difference_delta es su diferencia que puede usar por sus razones.

Hardik Patel
fuente
¿Es posible convertir el objeto timedelta de nuevo a datetime? Quiero decir que tenemos difference_delta .seconds (), ¿hay alguna forma de recuperar un objeto de fecha y hora? Thx
dejdej
Si. datetime.min + delta
sourcedelica
6

La biblioteca de python timedelta debería hacer lo que necesita. Se timedeltadevuelve A cuando resta dos datetimeinstancias.

import datetime
dt_started = datetime.datetime.utcnow()

# do some stuff

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

datetime.time no puedo hacerlo, pero podrías usar datetime.datetime.now()

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

Tuve una situación similar a la tuya y terminé usando una biblioteca externa llamada flecha .

Así es como se ve:

>>> import arrow
>>> enter = arrow.get('12:30:45', 'HH:mm:ss')
>>> exit = arrow.now()
>>> duration = exit - enter
>>> duration
datetime.timedelta(736225, 14377, 757451)
Rominf
fuente
1
Aquí solo está demostrando cómo restar objetos de fecha y hora completos, no horas del día como en la pregunta original
kleptog