Як обчислити інтервал часу між двома часовими рядками


169

У мене два рази, час початку та зупинки, у форматі 10:33:26 (HH: MM: SS). Мені потрібна різниця між двома разів. Я переглядав документацію для Python та здійснював пошук в Інтернеті, і можу уявити, що це має щось спільне з модулями дати та / або часу. Я не можу змусити його працювати належним чином і продовжую знаходити лише те, як це зробити, коли є дата.

Зрештою, мені потрібно обчислити середні значення за тривалістю часу. Я отримав різницю в часі для роботи, і я зберігаю їх у списку. Зараз мені потрібно порахувати середню. Я використовую регулярні вирази, щоб розібрати початкові часи, а потім зробити відмінності.

Чи слід конвертувати в середнє значення, а потім середнє?


2
Чи можете ви опублікувати свій код, який ви пробували, і ми можемо почати звідти?
Ентоні Форлоні

Відповіді:


200

Так, безумовно datetime, що вам тут потрібно. Зокрема, strptimeфункція, яка аналізує рядок на часовий об'єкт.

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)

Це дає вам timedeltaоб'єкт, який містить різницю між двома разів. З цим ви можете робити все, що завгодно, наприклад, перетворити його на секунди або додати його до іншого datetime.

Це поверне негативний результат, якщо час закінчення раніше, ніж час початку, наприклад, s1 = 12:00:00і s2 = 05:00:00. Якщо ви хочете, щоб у цьому випадку код передбачав інтервал перетину півночі (тобто він повинен вважати, що час закінчення ніколи не перевищує час початку), ви можете додати наступні рядки до вищевказаного коду:

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

(звичайно, потрібно from datetime import timedeltaдесь включити ). Дякуємо Дж. Ф. Себастьяну за те, що він вказав на цю справу використання.


Негативний days= -2злам часу не працюватиме, коли і вище в об’єкті tdelta.
CKM

@chandresh Так, але daysніколи не може бути -2 або менше без додаткової інформації (конкретно, дат) за межами описаної у питанні. Тож ця ситуація тут не актуальна.
David Z

3
Підказка: Щоб отримати дельту часу в секундах, вам потрібно зателефонувати tdelta.total_seconds().
scai

156

Спробуйте це - це ефективно для того, щоб визначити короткочасні події. Якщо щось займає більше години, то, напевно, для остаточного відображення потрібне дружнє форматування.

import time
start = time.time()

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

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

Різниця в часі повертається як кількість минулих секунд.


5
Чому це не було прийнятою відповіддю? Це просто, він дає значення, яке можна порівняти з чимось (чи виконувала моя команда більше 2,5 секунд на виконання?), І вона працює в v2.7
Мауг каже, що відновити Моніку

11
@Mawg Оскільки він не відповідає на питання ОП. Він запитував, як порівняти два різні часи, які він вже має у певному форматі, а не як генерувати їх, присвоївши події в своєму коді. Вони досить різні проблеми.
Natsukane

2
Ви не повинні використовувати це; використовувати натомість монотонний час ( time.monotonic()у Python). time.time()може йти назад (наприклад, коли час роботи машини змінюється, включаючи корективи NTP).
nemequ

1
Не має значення для питання
patricktokeeffe

14

Ось рішення, яке підтримує пошук різниці, навіть якщо час закінчення менший за час початку (протягом опівночі), наприклад 23:55:00-00:25:00(тривалість півгодини):

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

Вихідні дані

0:42:23
0:30:00

time_diff()повертає об'єкт timedelta, який ви можете передати (як частину послідовності) до mean()функції безпосередньо, наприклад:

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

mean()Результат також timedelta()об'єкт , який можна перетворити в секундах ( td.total_seconds()метод (з Python 2.7)), годинник ( td / timedelta(hours=1)(Python 3)) і т.д.


@JF Цікаво, чи зараз середньостатистичні функції та функції дисперсії працюють безпосередньо з об'єктом timedelta? Будь-яка думка з цього приводу? Також будь-яка допомога для обчислення дисперсії об'єктів timedelta буде корисною.
CKM

@chandresh: він не підтримується. Ви можете перетворити на секунди / мікросекунди для обчислення математичної статистики тиммедел.
jfs

11

Структура, що представляє різницю часу в Python, називається timedelta . Якщо у вас є start_timeта end_timeяк datetimeтипи, ви можете обчислити різницю за допомогою -оператора типу:

diff = end_time - start_time

ви повинні зробити це перед перетворенням у формат рядка particualr (наприклад, до start_time.strearch (...)). Якщо у вас вже є рядкове представлення, вам потрібно перетворити його назад у час / дату, використовуючи метод strptime .


10

Цей сайт каже, що спробувати:

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 

Цей форум використовує time.mktime ()


Переконайтесь, що якщо ви використовуєте% p (AM / PM), ви використовуєте% I (12 годин) замість% H (24 години): docs.python.org/2/library/…
Ендрю

6

Мені подобається, як це робить хлопець - https://amalgjose.com/2015/02/19/python-code-for-calculating-the-difference-bet between-two-time- stamps . Не впевнений, чи є у нього деякі мінуси.

Але виглядає для мене акуратно :)

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)

Щодо питання, який ви все ще повинні використовувати, datetime.strptime()як говорили інші раніше.


3

Спробуйте це

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

ВИХІД:

0:00:05

Ядро цієї відповіді зовсім не відрізняється від шестирічної та висококваліфікованої прийнятої відповіді. Ви насправді маєте що додати? Немає сенсу подавати абсолютно зайву відповідь.
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,
)

результат: 0 0 0 0 -47 -37


1

Обидва timeі datetimeмають компонент дати.

Зазвичай, якщо ви просто маєте справу з тимчасовою частиною, яку слід вказати за замовчуванням. Якщо ви просто зацікавлені в різниці і знаєте, що обидва рази перебувають в один і той же день, тоді побудуйте datetimeдля кожного з встановленим сьогоднішнім днем ​​і відніміть початок від часу зупинки, щоб отримати інтервал ( timedelta).


1

Погляньте на модуль дати та об’єкти timedelta. Ви повинні в кінцевому підсумку створити об'єкт дати для початку та зупинки, і коли ви віднімаєте їх, ви отримуєте тиммедель.


0

Короткий, якщо вас просто цікавить час, який минув 24 години. Ви можете відформатувати висновок за потребою у операторі 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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.