Как найти разницу во времени между двумя объектами datetime в python?

Ответы:

375
>>> import datetime
>>> first_time = datetime.datetime.now()
>>> later_time = datetime.datetime.now()
>>> difference = later_time - first_time
>>> seconds_in_day = 24 * 60 * 60
datetime.timedelta(0, 8, 562000)
>>> divmod(difference.days * seconds_in_day + difference.seconds, 60)
(0, 8)      # 0 minutes, 8 seconds

Вычитание более позднего времени из первого раза difference = later_time - first_timeсоздает объект datetime, который содержит только разницу. В приведенном выше примере это 0 минут, 8 секунд и 562000 микросекунд.

SilentGhost
источник
2
Ссылка: docs.python.org/library/datetime.html#datetime-objects . Читайте "поддерживаемые операции".
S.Lott
@SilentGhost, Как добраться с часами, минутами, секундами
Mulagala
1
@markcial: deloreanискажает datetime, pytzподход, например, пример кода для начала работы может быть записан как d = datetime.now(timezone(EST))(одна читаемая строка вместо пяти).
Jfs
1
примечание: вы должны быть осторожны при выполнении арифметики даты / времени на наивных объектах даты и времени, которые представляют местное время. Может произойти сбой, например, вокруг переходов DST. Смотрите ссылку с более подробной информацией в моем ответе
jfs
Как c используется, чтобы найти разницу в днях, мин, сек?
Зеешан Махмуд,
152

Новым в Python 2.7 является timedeltaметод экземпляра .total_seconds(). Из документов Python это эквивалентно (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6.

Ссылка: http://docs.python.org/2/library/datetime.html#datetime.timedelta.total_seconds

>>> import datetime
>>> time1 = datetime.datetime.now()
>>> time2 = datetime.datetime.now() # waited a few minutes before pressing enter
>>> elapsedTime = time2 - time1
>>> elapsedTime
datetime.timedelta(0, 125, 749430)
>>> divmod(elapsedTime.total_seconds(), 60)
(2.0, 5.749430000000004) # divmod returns quotient and remainder
# 2 minutes, 5.74943 seconds
Райан Стэнли
источник
107

Используя пример datetime

>>> from datetime import datetime
>>> then = datetime(2012, 3, 5, 23, 8, 15)        # Random date in the past
>>> now  = datetime.now()                         # Now
>>> duration = now - then                         # For build-in functions
>>> duration_in_s = duration.total_seconds()      # Total number of seconds between dates

Продолжительность в годах

>>> years = divmod(duration_in_s, 31536000)[0]    # Seconds in a year=365*24*60*60 = 31536000.

Продолжительность в днях

>>> days  = duration.days                         # Build-in datetime function
>>> days  = divmod(duration_in_s, 86400)[0]       # Seconds in a day = 86400

Продолжительность в часах

>>> hours = divmod(duration_in_s, 3600)[0]        # Seconds in an hour = 3600

Продолжительность в минутах

>>> minutes = divmod(duration_in_s, 60)[0]        # Seconds in a minute = 60

Продолжительность в секундах

>>> seconds = duration.seconds                    # Build-in datetime function
>>> seconds = duration_in_s

Продолжительность в микросекундах

>>> microseconds = duration.microseconds          # Build-in datetime function  

Общая продолжительность между двумя датами

>>> days    = divmod(duration_in_s, 86400)        # Get days (without [0]!)
>>> hours   = divmod(days[1], 3600)               # Use remainder of days to calc hours
>>> minutes = divmod(hours[1], 60)                # Use remainder of hours to calc minutes
>>> seconds = divmod(minutes[1], 1)               # Use remainder of minutes to calc seconds
>>> print("Time between dates: %d days, %d hours, %d minutes and %d seconds" % (days[0], hours[0], minutes[0], seconds[0]))

или просто:

>>> print(now - then)

Изменить 2019 Поскольку этот ответ набрал силу, я добавлю функцию, которая может упростить использование для некоторых

from datetime import datetime

def getDuration(then, now = datetime.now(), interval = "default"):

    # Returns a duration as specified by variable interval
    # Functions, except totalDuration, returns [quotient, remainder]

    duration = now - then # For build-in functions
    duration_in_s = duration.total_seconds() 

    def years():
      return divmod(duration_in_s, 31536000) # Seconds in a year=31536000.

    def days(seconds = None):
      return divmod(seconds if seconds != None else duration_in_s, 86400) # Seconds in a day = 86400

    def hours(seconds = None):
      return divmod(seconds if seconds != None else duration_in_s, 3600) # Seconds in an hour = 3600

    def minutes(seconds = None):
      return divmod(seconds if seconds != None else duration_in_s, 60) # Seconds in a minute = 60

    def seconds(seconds = None):
      if seconds != None:
        return divmod(seconds, 1)   
      return duration_in_s

    def totalDuration():
        y = years()
        d = days(y[1]) # Use remainder to calculate next variable
        h = hours(d[1])
        m = minutes(h[1])
        s = seconds(m[1])

        return "Time between dates: {} years, {} days, {} hours, {} minutes and {} seconds".format(int(y[0]), int(d[0]), int(h[0]), int(m[0]), int(s[0]))

    return {
        'years': int(years()[0]),
        'days': int(days()[0]),
        'hours': int(hours()[0]),
        'minutes': int(minutes()[0]),
        'seconds': int(seconds()),
        'default': totalDuration()
    }[interval]

# Example usage
then = datetime(2012, 3, 5, 23, 8, 15)
now = datetime.now()

print(getDuration(then)) # E.g. Time between dates: 7 years, 208 days, 21 hours, 19 minutes and 15 seconds
print(getDuration(then, now, 'years'))      # Prints duration in years
print(getDuration(then, now, 'days'))       #                    days
print(getDuration(then, now, 'hours'))      #                    hours
print(getDuration(then, now, 'minutes'))    #                    minutes
print(getDuration(then, now, 'seconds'))    #                    seconds
Attaque
источник
7
Я не знаю, почему никто не поблагодарил вас. Большое спасибо за такой точный ответ. @Attaque
Amandeep Singh
У меня есть ошибка TypeError: 'float' object is not subscriptableпри использовании для:then = datetime(2017, 8, 11, 15, 58, tzinfo=pytz.UTC) now = datetime(2018, 8, 11, 15, 58, tzinfo=pytz.UTC) getDuration(then, now, 'years')
Петр
1
Это потому, что я не могу посчитать количество секунд в году :) 365 * 24 * 60 * 60 = 31536000, а не 31556926. Я обновил ответ и функции, и теперь он должен работать.
Attaque
1
Это должен быть принятый ответ.
saran3h
28

Просто вычтите одно из другого. Вы получаете timedeltaобъект с разницей.

>>> import datetime
>>> d1 = datetime.datetime.now()
>>> d2 = datetime.datetime.now() # after a 5-second or so pause
>>> d2 - d1
datetime.timedelta(0, 5, 203000)

Вы можете конвертировать dd.days, dd.secondsи dd.microsecondsдо нескольких минут.

Винай Саджип
источник
Каковы эти параметры? Комментарии были бы хорошими
TheRealChx101
22

Если a, bявляются объектами datetime, то чтобы найти разницу во времени между ними в Python 3:

from datetime import timedelta

time_difference = a - b
time_difference_in_minutes = time_difference / timedelta(minutes=1)

В более ранних версиях Python:

time_difference_in_minutes = time_difference.total_seconds() / 60

Если a, bявляются наивными объектами даты и времени, такими как возвращенные, datetime.now()то результат может быть неправильным, если объекты представляют местное время с различными смещениями UTC, например, вокруг переходов DST или для прошлых / будущих дат. Более подробная информация: Найти, если между датами прошло 24 часа - Python .

Чтобы получить достоверные результаты, используйте объекты даты и времени с учетом времени UTC или часового пояса.

JFS
источник
17

Используйте divmod:

now = int(time.time()) # epoch seconds
then = now - 90000 # some time in the past

d = divmod(now-then,86400)  # days
h = divmod(d[1],3600)  # hours
m = divmod(h[1],60)  # minutes
s = m[1]  # seconds

print '%d days, %d hours, %d minutes, %d seconds' % (d[0],h[0],m[0],s)
tgwaste
источник
1
Это должно быть помещено в модуль datetime. Я просто не могу понять, почему он использовал только дни, секунды и миллис ...
paulochf
Это не отвечает на вопрос относительно объектов даты и времени.
elec3647
10

Вот как я получаю количество часов, прошедших между двумя объектами datetime.datetime:

before = datetime.datetime.now()
after  = datetime.datetime.now()
hours  = math.floor(((after - before).seconds) / 3600)
Тони
источник
9
Это не совсем сработает: timedelta.secondsтолько дает явно сохраненное количество секунд, которое, как гарантируют документы, составит менее одного дня. Вы хотите (after - before).total_seconds(), который дает количество секунд, которые охватывают всю дельту.
2013 г.
1
(after - before).total_seconds() // 3600(Python 2.7) или (after - before) // timedelta(seconds=3600)(Python 3)
JFS
@lvc Мой старый код был написан именно таким образом, и я подумал, что я умен и «исправляю» его. Спасибо за исправление.
Тони
@JFSebastian Спасибо за это, я забыл об операторе //. И мне нравится синтаксис py3 лучше, но я использую 2.7.
Тони
9

Чтобы просто найти количество дней: у timedelta есть атрибут days. Вы можете просто запросить это.

>>>from datetime import datetime, timedelta
>>>d1 = datetime(2015, 9, 12, 13, 9, 45)
>>>d2 = datetime(2015, 8, 29, 21, 10, 12)
>>>d3 = d1- d2
>>>print d3
13 days, 15:59:33
>>>print d3.days
13
griknus17
источник
5

Просто подумал, что было бы полезно упомянуть форматирование и в отношении timedelta. strptime () анализирует строку, представляющую время в соответствии с форматом.

from datetime import datetime

datetimeFormat = '%Y/%m/%d %H:%M:%S.%f'    
time1 = '2016/03/16 10:01:28.585'
time2 = '2016/03/16 09:56:28.067'  
time_dif = datetime.strptime(time1, datetimeFormat) - datetime.strptime(time2,datetimeFormat)
print(time_dif)

Это выведет: 0: 05: 00.518000

воробей
источник
3

Я использую что-то вроде этого:

from datetime import datetime

def check_time_difference(t1: datetime, t2: datetime):
    t1_date = datetime(
        t1.year,
        t1.month,
        t1.day,
        t1.hour,
        t1.minute,
        t1.second)

    t2_date = datetime(
        t2.year,
        t2.month,
        t2.day,
        t2.hour,
        t2.minute,
        t2.second)

    t_elapsed = t1_date - t2_date

    return t_elapsed

# usage 
f = "%Y-%m-%d %H:%M:%S+01:00"
t1 = datetime.strptime("2018-03-07 22:56:57+01:00", f)
t2 = datetime.strptime("2018-03-07 22:48:05+01:00", f)
elapsed_time = check_time_difference(t1, t2)

print(elapsed_time)
#return : 0:08:52
Softmixt
источник
2
Вы получаете очень хорошие даты, почему вы копируете их? это 75% вашего кода может быть выраженоreturn t1-t2
Патрик Артнер
2

это чтобы найти разницу между текущим временем и 9.30 утра.

t=datetime.now()-datetime.now().replace(hour=9,minute=30)
nidheesh
источник
1

Это мой подход с использованием mktime .

from datetime import datetime, timedelta
from time import mktime

yesterday = datetime.now() - timedelta(days=1)
today = datetime.now()

difference_in_seconds = abs(mktime(yesterday.timetuple()) - mktime(today.timetuple()))
difference_in_minutes = difference_in_seconds / 60
Эдуардо
источник
mktime()ожидает местное время в качестве входа. Местное время может быть неоднозначным и mktime()может дать неправильный ответ в этом случае. Используйте a - bвместо этого (a, b - объекты даты и времени) . mktime()ненужно и иногда неправильно. Не используйте это в этом случае.
Jfs
@AnneTheAgile, исправлено, моя вина в импорте. Проверено на Python 2.7.12
Эдуардо
1

Другими способами получить разницу между датами;

import dateutil.parser
import datetime
last_sent_date = "" # date string
timeDifference = current_date - dateutil.parser.parse(last_sent_date)
time_difference_in_minutes = (int(timeDifference.days) * 24 * 60) + int((timeDifference.seconds) / 60)

Получите вывод в мин.

Спасибо

Анураг Пандей
источник
1

Я использовал разницу во времени для непрерывных интеграционных тестов, чтобы проверить и улучшить свои функции. Вот простой код, если кому-то это нужно

from datetime import datetime

class TimeLogger:
    time_cursor = None

    def pin_time(self):
        global time_cursor
        time_cursor = datetime.now()

    def log(self, text=None) -> float:
        global time_cursor

        if not time_cursor:
            time_cursor = datetime.now()

        now = datetime.now()
        t_delta = now - time_cursor

        seconds = t_delta.total_seconds()

        result = str(now) + ' tl -----------> %.5f' % seconds
        if text:
            result += "   " + text
        print(result)

        self.pin_time()

        return seconds


time_logger = TimeLogger()

С помощью:

from .tests_time_logger import time_logger
class Tests(TestCase):
    def test_workflow(self):
    time_logger.pin_time()

    ... my functions here ...

    time_logger.log()

    ... other function(s) ...

    time_logger.log(text='Tests finished')

и у меня есть что-то подобное в выводе журнала

2019-12-20 17:19:23.635297 tl -----------> 0.00007
2019-12-20 17:19:28.147656 tl -----------> 4.51234   Tests finished
Серг Смык
источник
0

Основываясь на замечательном ответе @Attaque , я предлагаю более короткую упрощенную версию калькулятора разности даты и времени:

seconds_mapping = {
    'y': 31536000,
    'm': 2628002.88, # this is approximate, 365 / 12; use with caution
    'w': 604800,
    'd': 86400,
    'h': 3600,
    'min': 60,
    's': 1,
    'mil': 0.001,
}

def get_duration(d1, d2, interval, with_reminder=False):
    if with_reminder:
        return divmod((d2 - d1).total_seconds(), seconds_mapping[interval])
    else:
        return (d2 - d1).total_seconds() / seconds_mapping[interval]

Я изменил его, чтобы избежать объявления повторяющихся функций, убрал симпатичный интервал печати по умолчанию и добавил поддержку для миллисекунд, недель и месяцев ISO (голые в уме месяцы являются лишь приблизительными, исходя из предположения, что каждый месяц равен 365/12).

Который производит:

d1 = datetime(2011, 3, 1, 1, 1, 1, 1000)
d2 = datetime(2011, 4, 1, 1, 1, 1, 2500)

print(get_duration(d1, d2, 'y', True))      # => (0.0, 2678400.0015)
print(get_duration(d1, d2, 'm', True))      # => (1.0, 50397.12149999989)
print(get_duration(d1, d2, 'w', True))      # => (4.0, 259200.00149999978)
print(get_duration(d1, d2, 'd', True))      # => (31.0, 0.0014999997802078724)
print(get_duration(d1, d2, 'h', True))      # => (744.0, 0.0014999997802078724)
print(get_duration(d1, d2, 'min', True))    # => (44640.0, 0.0014999997802078724)
print(get_duration(d1, d2, 's', True))      # => (2678400.0, 0.0014999997802078724)
print(get_duration(d1, d2, 'mil', True))    # => (2678400001.0, 0.0004999997244524721)

print(get_duration(d1, d2, 'y', False))     # => 0.08493150689687975
print(get_duration(d1, d2, 'm', False))     # => 1.019176965856293
print(get_duration(d1, d2, 'w', False))     # => 4.428571431051587
print(get_duration(d1, d2, 'd', False))     # => 31.00000001736111
print(get_duration(d1, d2, 'h', False))     # => 744.0000004166666
print(get_duration(d1, d2, 'min', False))   # => 44640.000024999994
print(get_duration(d1, d2, 's', False))     # => 2678400.0015
print(get_duration(d1, d2, 'mil', False))   # => 2678400001.4999995
Voy
источник