566

How do I tell the time difference in minutes between two datetime objects?

dreftymac
  • 31,404
  • 26
  • 119
  • 182
Hobhouse
  • 15,463
  • 12
  • 35
  • 43

21 Answers21

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

Subtracting the later time from the first time difference = later_time - first_time creates a datetime object that only holds the difference. In the example above it is 0 minutes, 8 seconds and 562000 microseconds.

Milosz
  • 2,924
  • 3
  • 22
  • 24
SilentGhost
  • 307,395
  • 66
  • 306
  • 293
  • 4
    Reference: http://docs.python.org/library/datetime.html#datetime-objects. Read "supported operations". – S.Lott Aug 28 '09 at 10:08
  • @SilentGhost, How to get with hours,minuits,seconds – Mulagala Jun 14 '14 at 07:01
  • 1
    @markcial: `delorean` misrepresents `datetime`, `pytz` approach e.g., [the getting started code example](http://delorean.readthedocs.org/en/latest/#getting-started) could be written as `d = datetime.now(timezone(EST))` (one readable line instead of five). – jfs Jan 10 '15 at 08:57
  • 1
    note: you should be careful when performing date/time arithmetics on naive datetime objects that represent local time. It may fail e.g., around DST transitions. See [the link with more details in my answer](http://stackoverflow.com/a/26586909/4279) – jfs Jan 10 '15 at 08:59
  • How is c used to find difference in terms of days, min, sec? – Zeeshan Jan 22 '16 at 06:50
  • We have a great representation for timedelta objects. Use str(c) to represent clean data in simple time format. '0:00:09.526000' – Doogle Apr 11 '18 at 04:24
  • some description would be helpful – Sameh Sharaf Apr 20 '18 at 04:00
  • In case you're wondering like me what these numbers are, e.g. 562000, it's microseconds, see the docs for [timedelta](https://docs.python.org/3/library/datetime.html#datetime.timedelta) – Davos Apr 24 '18 at 07:12
  • How can this be used to get hour as well? – Shameer Kashif May 21 '21 at 20:58
  • @ShameerKashif Try `divmod(diff.days * (seconds_in_day / 60) + (diff.seconds / 60), 60)`. Essentially converts to mins, so gives you the # of hours and mins. – rideron89 Sep 10 '21 at 19:52
  • This answer is not really correct. For example, two different real datetimes (as measured by their EPOCH seconds) may have a timedelta difference of zero! It is in the Python specs. – Wolfgang Kuehn Dec 10 '21 at 15:16
275

Using datetime example

>>> 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

Duration in years

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

Duration in days

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

Duration in hours

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

Duration in minutes

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

Duration in seconds

[!] See warning about using duration in seconds in the bottom of this post

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

Duration in microseconds

[!] See warning about using duration in microseconds in the bottom of this post

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

Total duration between the two dates

>>> 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]))

or simply:

>>> print(now - then)

Edit 2019 Since this answer has gained traction, I'll add a function, which might simplify the usage for some

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

Warning: Caveat about built-in .seconds and .microseconds
datetime.seconds and datetime.microseconds are capped to [0,86400) and [0,10^6) respectively.

They should be used carefully if timedelta is bigger than the max returned value.

Examples:

end is 1h and 200μs after start:

>>> start = datetime(2020,12,31,22,0,0,500)
>>> end = datetime(2020,12,31,23,0,0,700)
>>> delta = end - start
>>> delta.microseconds
RESULT: 200
EXPECTED: 3600000200

end is 1d and 1h after start:

>>> start = datetime(2020,12,30,22,0,0)
>>> end = datetime(2020,12,31,23,0,0)
>>> delta = end - start
>>> delta.seconds
RESULT: 3600
EXPECTED: 90000
Nicolai Lissau
  • 7,298
  • 5
  • 43
  • 57
  • I've got error `TypeError: 'float' object is not subscriptable` when use for: `then = datetime(2017, 8, 11, 15, 58, tzinfo=pytz.UTC)` `now = datetime(2018, 8, 11, 15, 58, tzinfo=pytz.UTC)` `getDuration(then, now, 'years')` – Piotr Wasilewicz Nov 20 '19 at 10:34
  • 1
    That's because I can't count the number of seconds in a year :) 365*24*60*60 = 31536000 and not 31556926. I updated the answer and the functions and it should work now. – Nicolai Lissau Nov 20 '19 at 11:40
  • what about including leap years? – rgenito Oct 25 '20 at 00:24
  • 1
    @DenisdaMata the edit you applied doesn't make the post any better, I understand that your intentions were to make copying and pasting easy. But this edit decreases readability and makes it harder to differentiate between code and output. Please avoid suggesting edits that only remove the `>>>` from code. – Sabito stands with Ukraine Feb 15 '21 at 02:01
  • What about months? – parsecer Mar 16 '21 at 20:36
  • `totalDuration` is totally broken. Returns -1 years, 364 days, 23 hours, 59 minutes and 54 seconds after not even a second ... Running Python 3.9.10 – Got To Figure Mar 25 '22 at 01:47
170

New at Python 2.7 is the timedelta instance method .total_seconds(). From the Python docs, this is equivalent to (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6.

Reference: 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
Ryan Stanley
  • 1,809
  • 1
  • 11
  • 4
  • 10
    you could [use `elapsedTime / timedelta(minutes=1)` to get the difference in minutes in Python 3](http://stackoverflow.com/a/26586909/4279) – jfs Oct 27 '14 at 11:50
60

Just subtract one from the other. You get a timedelta object with the difference.

>>> 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 = d2 - d1
>>> print (dd.days) # get days
>>> print (dd.seconds) # get seconds
>>> print (dd.microseconds) # get microseconds
>>> print (int(round(dd.total_seconds()/60, 0))) # get minutes
Vinay Sajip
  • 95,872
  • 14
  • 179
  • 191
37

If a, b are datetime objects then to find the time difference between them in Python 3:

from datetime import timedelta

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

On earlier Python versions:

time_difference_in_minutes = time_difference.total_seconds() / 60

If a, b are naive datetime objects such as returned by datetime.now() then the result may be wrong if the objects represent local time with different UTC offsets e.g., around DST transitions or for past/future dates. More details: Find if 24 hrs have passed between datetimes - Python.

To get reliable results, use UTC time or timezone-aware datetime objects.

Community
  • 1
  • 1
jfs
  • 399,953
  • 195
  • 994
  • 1,670
20

Use 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
  • 439
  • 3
  • 7
14

To just find the number of days: timedelta has a 'days' attribute. You can simply query that.

>>>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
  • 159
  • 1
  • 4
13

This is how I get the number of hours that elapsed between two datetime.datetime objects:

before = datetime.datetime.now()
after  = datetime.datetime.now()
hours  = math.floor(((after - before).seconds) / 3600)
Tony
  • 2,037
  • 3
  • 22
  • 22
  • 10
    This won't quite work: `timedelta.seconds` only gives the number of seconds *explicitly stored* - which the documentation guarantees will total less than one day. You want `(after - before).total_seconds()`, which gives the number of seconds that span the *entire* delta. – lvc May 26 '13 at 01:25
  • 1
    `(after - before).total_seconds() // 3600` (Python 2.7) or `(after - before) // timedelta(seconds=3600)` (Python 3) – jfs May 26 '13 at 02:09
  • @lvc My old code was actually written that way, and I thought I was being smart and "fixing" it up. Thanks for the correction. – Tony May 26 '13 at 23:08
  • @J.F.Sebastian Thanks for that, I forgot about the // operator. And I do I like the py3 syntax better, but am using 2.7. – Tony May 26 '13 at 23:10
13

Just thought it might be useful to mention formatting as well in regards to timedelta. strptime() parses a string representing a time according to a format.

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)

This will output: 0:05:00.518000

sparrow
  • 10,794
  • 12
  • 54
  • 74
7

To get the hour, minute and second, you can do this

>>> import datetime
>>> first_time = datetime.datetime.now()
>>> later_time = datetime.datetime.now()
>>> difference = later_time - first_time
>>> m, s = divmod(difference.total_seconds(), 60)
>>> print("H:M:S is {}:{}:{}".format(m//60, m%60, s))
P A N
  • 5,642
  • 15
  • 52
  • 103
4

I use somethign like this :

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
  • 1,658
  • 20
  • 20
  • 3
    you get perfectly good datetimes in, why do you copy them over? thats 75% of your code can be expressed by `return t1-t2` – Patrick Artner Jun 20 '18 at 19:54
3

This will give the difference in seconds (then just divide by 60 to get minutes):

import time
import datetime

t_start = datetime.datetime.now()

time.sleep(10)

t_end = datetime.datetime.now()
elapsedTime = (t_end - t_start )

print(elapsedTime.total_seconds())

outputs:

10.009222

This is the simplest way in my opinion, and you don't need to worry about precision or overflow.

For instance, using elapsedTime.seconds you lose a lot of precision (it returns an integer). Also, elapsedTime.microseconds is capped at 10^6, as this answer pointed out. So, for example, for a 10 second sleep(), elapsedTime.microseconds gives 8325 (which is wrong, should be around 10,000,000).

Bersan
  • 1,032
  • 1
  • 17
  • 28
2

this is to find the difference between current time and 9.30 am

t=datetime.now()-datetime.now().replace(hour=9,minute=30)
nidheesh
  • 31
  • 1
2

Based on @Attaque great answer, I propose a shorter simplified version of the datetime difference calculator:

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]

I've changed it to avoid declaring repetetive functions, removed the pretty print default interval and added support for milliseconds, weeks and ISO months (bare in mind months are just approximate, based on assumption that each month is equal to 365/12).

Which produces:

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
  • 5,286
  • 1
  • 49
  • 59
1

This is my approach using 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
Eduardo
  • 4,282
  • 2
  • 49
  • 63
  • `mktime()` expects local time as an input. Local time maybe ambiguous and `mktime()` may return a wrong answer in this case. [Use `a - b` instead (a,b - datetime objects)](http://stackoverflow.com/a/26586909/4279). `mktime()` is unnecessary and it is sometimes wrong. Don't use it in this case. – jfs Oct 27 '14 at 11:45
  • @AnneTheAgile, fixed, my fault on the import. Tested on Python 2.7.12 – Eduardo Oct 03 '16 at 08:53
1

In Other ways to get difference between date;

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)

So get output in Min.

Thanks

Anurag Pandey
  • 744
  • 1
  • 7
  • 14
1

I have used time differences for continuous integration tests to check and improve my functions. Here is simple code if somebody need it

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

Using:

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')

and i have something like that in log output

2019-12-20 17:19:23.635297 tl -----------> 0.00007
2019-12-20 17:19:28.147656 tl -----------> 4.51234   Tests finished
Serg Smyk
  • 613
  • 5
  • 11
1

You may find this fast snippet useful in not so much long time intervals:

    from datetime import datetime as dttm
    time_ago = dttm(2017, 3, 1, 1, 1, 1, 1348)
    delta = dttm.now() - time_ago
    days = delta.days # can be converted into years which complicates a bit…
    hours, minutes, seconds = map(int, delta.__format__('').split('.')[0].split(' ')[-1].split(':'))

tested on Python v.3.8.6

LordBlick
  • 26
  • 3
1

Here is an answer that is easy to generalise or turn into a function and which is reasonable compact and easy to follow.

ts_start=datetime(2020, 12, 1, 3, 9, 45)
ts_end=datetime.now()
ts_diff=ts_end-ts_start
secs=ts_diff.total_seconds()
days,secs=divmod(secs,secs_per_day:=60*60*24)
hrs,secs=divmod(secs,secs_per_hr:=60*60)
mins,secs=divmod(secs,secs_per_min:=60)
secs=round(secs, 2)
answer='Duration={} days, {} hrs, {} mins and {} secs'.format(int(days),int(hrs),int(mins),secs)
print(answer)

It gives an answer in the form Duration=270 days, 10 hrs, 32 mins and 42.13 secs

Mark Kortink
  • 1,770
  • 4
  • 21
  • 36
0

This might help someone, find is expired or not with this method its calculating with days. There are dt.seconds and dt.microseconds also available

from datetime import datetime
# updated_at = "2022-10-20T07:18:56.950563"
def is_expired(updated_at):
    expires_in = 7 #days
    datetime_format = '%Y-%m-%dT%H:%M:%S.%f'
    time_difference = datetime.now() - datetime.strptime(updated_at, datetime_format)

    return True if time_difference.days > expires_in else False
firozSujan
  • 118
  • 1
  • 9
-1
import datetime
date = datetime.date(1, 1, 1)
#combine a dummy date to the time
datetime1 = datetime.datetime.combine(date, start_time)
datetime2 = datetime.datetime.combine(date, stop_time)  
#compute the difference
time_elapsed = datetime1 - datetime2

start_time --> start time for datetime object
end_time--> end time for datetime object

we cannot directly subtract the datetime.time objects
hence we need to add a random date to it (we use combine)
or you can use the "today" instead of (1,1,1)

hope this helps

code-freeze
  • 465
  • 8
  • 8
  • 2
    What is `start_time` and `stop_time`? Why do you need to append some random 1/1/1 date? If they are both `datetime` objects already, you can apply `-` directly. – Gino Mempin Apr 06 '21 at 00:03