Comment calculer l'intervalle de temps entre deux chaînes de temps

169

J'ai deux heures, une heure de début et une heure de fin, au format 10:33:26 (HH: MM: SS). J'ai besoin de la différence entre les deux fois. J'ai parcouru la documentation pour Python et effectué des recherches en ligne et j'imagine que cela aurait quelque chose à voir avec les modules datetime et / ou time. Je n'arrive pas à le faire fonctionner correctement et je n'arrête pas de trouver comment le faire lorsqu'une date est impliquée.

En fin de compte, j'ai besoin de calculer les moyennes de plusieurs durées. J'ai fait fonctionner les décalages horaires et je les stocke dans une liste. Je dois maintenant calculer la moyenne. J'utilise des expressions régulières pour analyser les temps originaux et ensuite faire les différences.

Pour la moyenne, dois-je convertir en secondes puis en moyenne?

Hannah
la source
2
Pouvez-vous poster votre code que vous avez essayé et nous pouvons commencer à partir de là?
Anthony Forloney

Réponses:

201

Oui, c'est certainement datetimece dont vous avez besoin ici. Plus précisément, la strptimefonction, qui analyse une chaîne dans un objet de temps.

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)

Cela vous donne un timedeltaobjet qui contient la différence entre les deux temps. Vous pouvez faire ce que vous voulez avec cela, par exemple le convertir en secondes ou l'ajouter à un autre datetime.

Cela renverra un résultat négatif si l'heure de fin est antérieure à l'heure de début, par exemple s1 = 12:00:00et s2 = 05:00:00. Si vous voulez que le code suppose que l'intervalle traverse minuit dans ce cas (c'est-à-dire qu'il doit supposer que l'heure de fin n'est jamais antérieure à l'heure de début), vous pouvez ajouter les lignes suivantes au code ci-dessus:

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

(bien sûr, vous devez inclure from datetime import timedeltaquelque part). Merci à JF Sebastian d'avoir signalé ce cas d'utilisation.

David Z
la source
Le piratage en temps négatif ne fonctionnera pas quand days= -2et plus dans l'objet tdelta.
CKM
@chandresh Oui, mais daysne peut jamais être -2 ou moins sans qu'il y ait des informations supplémentaires (spécifiquement, des dates) au-delà de ce qui est décrit dans la question. Cette situation n'est donc pas pertinente ici.
David Z
3
Astuce: pour obtenir le décalage horaire en secondes, vous devez appeler tdelta.total_seconds().
scai
156

Essayez ceci - c'est efficace pour chronométrer des événements à court terme. Si quelque chose prend plus d'une heure, l'affichage final voudra probablement un formatage convivial.

import time
start = time.time()

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

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

Le décalage horaire est renvoyé sous forme de nombre de secondes écoulées.

Bill Grava
la source
5
Pourquoi n'était-ce pas la réponse acceptée? C'est simple, cela donne une valeur qui peut être comparée à quelque chose (ma commande a-t-elle pris plus de 2,5 secondes pour s'exécuter?) Et cela fonctionne dans la v2.7
Mawg dit réintégrer Monica le
11
@Mawg Parce qu'il ne répond pas à la question des OP. Il demandait comment comparer deux heures différentes qu'il a déjà dans un certain format, pas comment les générer en chronométrant un événement dans son code. Ce sont des problèmes assez différents.
Natsukane le
2
Vous ne devriez pas utiliser ceci; utilisez plutôt le temps monotone ( time.monotonic()en Python). time.time()peut reculer (par exemple, lorsque l'heure sur la machine change, y compris les corrections NTP).
nemequ
1
Sans rapport avec la question
patricktokeeffe
14

Voici une solution qui prend en charge la recherche de la différence même si l'heure de fin est inférieure à l'heure de début (sur un intervalle de minuit) comme 23:55:00-00:25:00(une durée d'une demi-heure):

#!/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())

Production

0:42:23
0:30:00

time_diff()renvoie un objet timedelta que vous pouvez passer (en tant que partie de la séquence) à une mean()fonction directement, par exemple:

#!/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

Le mean()résultat est également un timedelta()objet que vous pouvez convertir en secondes ( td.total_seconds()méthode (depuis Python 2.7)), heures ( td / timedelta(hours=1)(Python 3)), etc.

jfs
la source
@JF Je me demande si les fonctions de moyenne et de variance des statistiques fonctionnent maintenant directement avec l'objet timedelta? Une pensée à ce sujet? De plus, toute aide pour calculer la variance des objets timedelta sera utile.
CKM
@chandresh: il n'est pas pris en charge. Vous pouvez convertir en secondes / microsecondes pour calculer les statistiques mathématiques des timedeltas.
jfs
11

La structure qui représente le décalage horaire en Python est appelée timedelta . Si vous avez start_timeet en end_timetant que datetimetypes, vous pouvez calculer la différence en utilisant un -opérateur comme:

diff = end_time - start_time

vous devriez le faire avant de convertir au format de chaîne particulière (par exemple, avant start_time.strftime (...)). Si vous avez déjà une représentation sous forme de chaîne, vous devez la reconvertir en time / datetime à l'aide de la méthode strptime .

Dzida
la source
10

Ce site dit d'essayer:

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 

Ce forum utilise time.mktime ()

Kyra
la source
Assurez-vous que si vous utilisez% p (AM / PM) que vous utilisez% I (12 heures) au lieu de% H (24 heures): docs.python.org/2/library/…
Andrew
6

J'aime la façon dont ce gars le fait - https://amalgjose.com/2015/02/19/python-code-for-calculating-the-difference-between-two-time-stamps . Je ne sais pas si cela a des inconvénients.

Mais ça me va bien :)

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)

En ce qui concerne la question, vous devez toujours utiliser datetime.strptime()comme d'autres l'ont dit plus tôt.

Antonavy
la source
3

Essaye ça

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

PRODUCTION :

0:00:05
Dipnesh Parakhiya
la source
Le cœur de cette réponse ne diffère pas du tout de la réponse acceptée de six ans et hautement votée. Avez-vous quelque chose à ajouter? Il ne sert à rien de soumettre une réponse complètement redondante.
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,
)

résultat: 0 0 0 0-47-37

hu est allé
la source
1

Les deux timeet datetimeont un composant de date.

Normalement, si vous ne traitez que la partie horaire, vous fournirez une date par défaut. Si vous êtes simplement intéressé par la différence et que vous savez que les deux heures sont le même jour, construisez un datetimepour chacune avec le jour défini sur aujourd'hui et soustrayez le début de l'heure de fin pour obtenir l'intervalle ( timedelta).

ChrisF
la source
1

Jetez un œil au module datetime et aux objets timedelta. Vous devriez finir par construire un objet datetime pour les heures de début et de fin, et lorsque vous les soustrayez, vous obtenez un timedelta.

transpercer
la source
0

Concis si vous êtes simplement intéressé par le temps écoulé qui est inférieur à 24 heures. Vous pouvez formater la sortie selon vos besoins dans l'instruction return:

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)
user2654744
la source