Cómo calcular el intervalo de tiempo entre dos cadenas de tiempo

169

Tengo dos veces, una hora de inicio y una de parada, en el formato de 10:33:26 (HH: MM: SS). Necesito la diferencia entre las dos veces. He estado revisando la documentación de Python y buscando en línea, y me imagino que tendría algo que ver con los módulos de fecha y hora. No puedo hacer que funcione correctamente y sigo buscando solo cómo hacerlo cuando hay una cita involucrada.

En última instancia, necesito calcular los promedios de múltiples duraciones de tiempo. Tengo las diferencias horarias para trabajar y las estoy almacenando en una lista. Ahora necesito calcular el promedio. Estoy usando expresiones regulares para analizar los tiempos originales y luego hago las diferencias.

Para el promedio, ¿debo convertir a segundos y luego a la media?

Hannah
fuente
2
¿Puedes publicar el código que has probado y podemos comenzar desde allí?
Anthony Forloney

Respuestas:

201

Sí, definitivamente datetimees lo que necesitas aquí. Específicamente, la strptimefunción, que analiza una cadena en un objeto de tiempo.

from datetime import datetime
s1 = '10:33:26'
s2 = '11:15:49' # for example
FMT = '%H:%M:%S'
tdelta = datetime.strptime(s2, FMT) - datetime.strptime(s1, FMT)

Eso te da un timedeltaobjeto que contiene la diferencia entre las dos veces. Puede hacer lo que quiera con eso, por ejemplo, convertirlo en segundos o agregarlo a otro datetime.

Esto devolverá un resultado negativo si la hora de finalización es anterior a la hora de inicio, por ejemplo, s1 = 12:00:00y s2 = 05:00:00. Si desea que el código asuma que el intervalo cruza la medianoche en este caso (es decir, debe suponer que la hora de finalización nunca es anterior a la hora de inicio), puede agregar las siguientes líneas al código anterior:

if tdelta.days < 0:
    tdelta = timedelta(days=0,
                seconds=tdelta.seconds, microseconds=tdelta.microseconds)

(Por supuesto, debe incluir en from datetime import timedeltaalguna parte). Gracias a JF Sebastian por señalar este caso de uso.

David Z
fuente
El truco de tiempo negativo no funcionará cuando days= -2y arriba en el objeto tdelta.
CKM
@chandresh Sí, pero daysnunca puede ser -2 o menos sin que haya información adicional (específicamente, fechas) más allá de lo que se describe en la pregunta. Entonces esa situación no es relevante aquí.
David Z
3
Sugerencia: Para obtener el tiempo delta en segundos, debe llamar tdelta.total_seconds().
scai
156

Pruebe esto: es eficiente para cronometrar eventos a corto plazo. Si algo lleva más de una hora, entonces la pantalla final probablemente querrá un formato amigable.

import time
start = time.time()

time.sleep(10)  # or do something more productive

done = time.time()
elapsed = done - start
print(elapsed)

La diferencia de tiempo se devuelve como el número de segundos transcurridos.

Bill Grava
fuente
55
¿Por qué no fue esta la respuesta aceptada? Es simple, le da un valor que se puede comparar con algo (¿mi comando tardó más de 2.5 segundos en ejecutarse?) Y funciona en v2.7
Mawg dice que reinstale a Monica el
11
@Mawg Porque no responde la pregunta de los OP. Estaba preguntando cómo comparar dos veces diferentes que ya tiene en un formato determinado, no cómo generarlas cronometrando un evento en su código. Son problemas bastante diferentes.
Natsukane
2
No deberías usar esto; use tiempo monótono en su lugar ( time.monotonic()en Python). time.time()puede retroceder (p. ej., cuando cambia el tiempo en la máquina, incluidas las correcciones NTP).
nemequ
1
Irrelevante a la pregunta
patricktokeeffe
14

Aquí hay una solución que admite encontrar la diferencia, incluso si la hora de finalización es menor que la hora de inicio (durante el intervalo de medianoche) como 23:55:00-00:25:00(media hora de duración):

#!/usr/bin/env python
from datetime import datetime, time as datetime_time, timedelta

def time_diff(start, end):
    if isinstance(start, datetime_time): # convert to datetime
        assert isinstance(end, datetime_time)
        start, end = [datetime.combine(datetime.min, t) for t in [start, end]]
    if start <= end: # e.g., 10:33:26-11:15:49
        return end - start
    else: # end < start e.g., 23:55:00-00:25:00
        end += timedelta(1) # +day
        assert end > start
        return end - start

for time_range in ['10:33:26-11:15:49', '23:55:00-00:25:00']:
    s, e = [datetime.strptime(t, '%H:%M:%S') for t in time_range.split('-')]
    print(time_diff(s, e))
    assert time_diff(s, e) == time_diff(s.time(), e.time())

Salida

0:42:23
0:30:00

time_diff()devuelve un objeto timedelta que puede pasar (como parte de la secuencia) a una mean()función directamente, por ejemplo:

#!/usr/bin/env python
from datetime import timedelta

def mean(data, start=timedelta(0)):
    """Find arithmetic average."""
    return sum(data, start) / len(data)

data = [timedelta(minutes=42, seconds=23), # 0:42:23
        timedelta(minutes=30)] # 0:30:00
print(repr(mean(data)))
# -> datetime.timedelta(0, 2171, 500000) # days, seconds, microseconds

El mean()resultado también es un timedelta()objeto que puede convertir a segundos ( td.total_seconds()método (desde Python 2.7)), horas ( td / timedelta(hours=1)(Python 3)), etc.

jfs
fuente
@JF Me pregunto si las funciones de media y varianza de estadísticas funcionan directamente con el objeto timedelta ahora. ¿Alguna idea sobre eso? Además, cualquier ayuda para calcular la varianza de los objetos timedelta será útil.
CKM
@chandresh: no es compatible. Puede convertir a segundos / microsegundos para calcular estadísticas matemáticas de timedeltas.
jfs
11

La estructura que representa la diferencia horaria en Python se llama timedelta . Si tiene start_timey end_timecomo datetimetipos, puede calcular la diferencia utilizando un -operador como:

diff = end_time - start_time

debe hacer esto antes de convertir a un formato de cadena particular (por ejemplo, antes de start_time.strftime (...)). En caso de que ya tenga una representación de cadena, debe convertirla nuevamente a hora / fecha y hora utilizando el método strptime .

dzida
fuente
10

Este sitio dice que intente:

import datetime as dt
start="09:35:23"
end="10:23:00"
start_dt = dt.datetime.strptime(start, '%H:%M:%S')
end_dt = dt.datetime.strptime(end, '%H:%M:%S')
diff = (end_dt - start_dt) 
diff.seconds/60 

Este foro utiliza time.mktime ()

Kyra
fuente
Asegúrese de que si usa% p (AM / PM) usa% I (12 horas) en lugar de% H (24 horas): docs.python.org/2/library/…
Andrew
6

Me gusta cómo lo hace este tipo: https://amalgjose.com/2015/02/19/python-code-for-calculating-the-difference-between-two-time-stamps . No estoy seguro si tiene algunas desventajas.

Pero se ve bien para mí :)

from datetime import datetime
from dateutil.relativedelta import relativedelta

t_a = datetime.now()
t_b = datetime.now()

def diff(t_a, t_b):
    t_diff = relativedelta(t_b, t_a)  # later/end time comes first!
    return '{h}h {m}m {s}s'.format(h=t_diff.hours, m=t_diff.minutes, s=t_diff.seconds)

Con respecto a la pregunta que todavía necesita usar datetime.strptime()como otros dijeron antes.

antonavy
fuente
3

Prueba esto

import datetime
import time
start_time = datetime.datetime.now().time().strftime('%H:%M:%S')
time.sleep(5)
end_time = datetime.datetime.now().time().strftime('%H:%M:%S')
total_time=(datetime.datetime.strptime(end_time,'%H:%M:%S') - datetime.datetime.strptime(start_time,'%H:%M:%S'))
print total_time

SALIDA

0:00:05
Dipnesh Parakhiya
fuente
El núcleo de esta respuesta no difiere en absoluto de la respuesta aceptada de seis años y altamente votada. ¿Realmente tienes algo que agregar? No tiene sentido enviar una respuesta completamente redundante.
Blckknght
2
import datetime as dt
from dateutil.relativedelta import relativedelta

start = "09:35:23"
end = "10:23:00"
start_dt = dt.datetime.strptime(start, "%H:%M:%S")
end_dt = dt.datetime.strptime(end, "%H:%M:%S")
timedelta_obj = relativedelta(start_dt, end_dt)
print(
    timedelta_obj.years,
    timedelta_obj.months,
    timedelta_obj.days,
    timedelta_obj.hours,
    timedelta_obj.minutes,
    timedelta_obj.seconds,
)

resultado: 0 0 0 0 -47 -37

hu wentao
fuente
1

Ambos timey datetimetienen un componente de fecha.

Normalmente, si solo está tratando con la parte del tiempo, proporcionaría una fecha predeterminada. Si solo está interesado en la diferencia y sabe que ambas horas son el mismo día, construya un datetimepara cada una con el día establecido hoy y reste el inicio de la hora de finalización para obtener el intervalo ( timedelta).

ChrisF
fuente
1

Eche un vistazo al módulo datetime y los objetos timedelta. Debes terminar construyendo un objeto datetime para las horas de inicio y finalización, y cuando las restas, obtienes una timedelta.

atravesar
fuente
0

Conciso si solo está interesado en el tiempo transcurrido que es inferior a 24 horas. Puede formatear la salida según sea necesario en la declaración de devolución:

import datetime
def elapsed_interval(start,end):
    elapsed = end - start
    min,secs=divmod(elapsed.days * 86400 + elapsed.seconds, 60)
    hour, minutes = divmod(min, 60)
    return '%.2d:%.2d:%.2d' % (hour,minutes,secs)

if __name__ == '__main__':
    time_start=datetime.datetime.now()
    """ do your process """
    time_end=datetime.datetime.now()
    total_time=elapsed_interval(time_start,time_end)
usuario2654744
fuente