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.

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.


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.


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)

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.


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.


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

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 no puedo hacerlo, pero podrías usar datetime.datetime.now()

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

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)

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.