288

There has to be an easier way to do this. I have objects that want to be refreshed every so often, so I want to record when they were created, check against the current timestamp, and refresh as necessary.

datetime.datetime has proven to be difficult, and I don't want to dive into the ctime library. Is there anything easier for this sort of thing?

Kara
  • 6,115
  • 16
  • 50
  • 57
alexgolec
  • 26,898
  • 33
  • 107
  • 159

7 Answers7

738

if you want to compute differences between two known dates, use total_seconds like this:

import datetime as dt

a = dt.datetime(2013,12,30,23,59,59)
b = dt.datetime(2013,12,31,23,59,59)

(b-a).total_seconds()

86400.0

#note that seconds doesn't give you what you want:
(b-a).seconds

0

Rich Signell
  • 14,842
  • 4
  • 49
  • 77
  • 149
    The `note' is the most important part which people miss. I wish I could give another up vote on it. – Dexter Sep 15 '13 at 19:59
  • There are times where I notice it gives a seemingly...incorrect result. 59.800 seconds for a split second difference. So, for smaller operations, such as difference of seconds, milliseconds, or microseconds, one could use `(b-a).microseconds` and then divide that to get the seconds (1000000) or milliseconds (1000) – Zld Productions May 26 '17 at 16:22
  • it appears the value is always positive, even when a and b are swapped – Nickpick Mar 10 '18 at 00:02
  • @Nickpick the value is not always positive. e.g. the following is `-60`: `from datetime import datetime; (datetime(2019, 1, 1, 0, 0) - datetime(2019, 1, 1, 0, 1)).total_seconds()` – JDiMatteo Jan 02 '19 at 02:06
  • Impressive solution! Clean code not being necessary to create functions. – Paulo Fabrício Mar 29 '19 at 11:26
  • 6
    This helped a lot. But why does python always give the wrong answer for `(b-a).seconds`? – enchance Jun 27 '21 at 13:23
  • 6
    @enchance it's because (b-a).seconds mean only seconds part of the difference. There are also (b-a).minutes , (b-a).hours, ... – Septacle Jul 02 '21 at 16:19
  • thanks for the footnote! that's what I was wondering!!! – ujjaldey Feb 03 '23 at 16:17
48
import time  
current = time.time()

...job...
end = time.time()
diff = end - current

would that work for you?

matcheek
  • 4,887
  • 9
  • 42
  • 73
  • 3
    +1; we don't really care about the date of either invocation - we care about the elapsed time. So just use a raw timestamp, as shown. – Karl Knechtel Dec 06 '10 at 01:58
20
>>> from datetime import datetime

>>>  a = datetime.now()

# wait a bit 
>>> b = datetime.now()

>>> d = b - a # yields a timedelta object
>>> d.seconds
7

(7 will be whatever amount of time you waited a bit above)

I find datetime.datetime to be fairly useful, so if there's a complicated or awkward scenario that you've encountered, please let us know.

EDIT: Thanks to @WoLpH for pointing out that one is not always necessarily looking to refresh so frequently that the datetimes will be close together. By accounting for the days in the delta, you can handle longer timestamp discrepancies:

>>> a = datetime(2010, 12, 5)
>>> b = datetime(2010, 12, 7)
>>> d = b - a
>>> d.seconds
0
>>> d.days
2
>>> d.seconds + d.days * 86400
172800
Jarret Hardie
  • 95,172
  • 10
  • 132
  • 126
  • 1
    If you return `d.seconds + d.days * 86400` instead, it's correct for multiple days ;) – Wolph Dec 06 '10 at 01:40
  • 9
    Note that, in the general case, this is *not correct*. Consider the case `a - b`, where `a` is *before* `b` (ie, so the result will be negative): `(a - b).seconds == 86282` while `a - b == datetime.timedelta(-1, 86276, 627665)`. The correct method, I believe, is to use `timedelta.total_seconds()`… But that is py2.7+ only. – David Wolever Aug 10 '11 at 16:19
  • 9
    Indeed, the answer is not right and should reflect @DavidWolever comment. The correct answer is: use `timedelta.total_seconds()`. Downvoted accordingly. – astrojuanlu Jun 15 '13 at 14:16
  • 3
    Upvoted for Python 2.6 answer. `total_seconds()` is a 2.7+ feature. – Joe Holloway Feb 13 '14 at 23:55
  • @JoeHolloway I guess that this isn't working correctly in Python 2.6 too. – Vladimir Chub Apr 23 '18 at 07:52
12

We have function total_seconds() with Python 2.7 Please see below code for python 2.6

import datetime
import time  

def diffdates(d1, d2):
    #Date format: %Y-%m-%d %H:%M:%S
    return (time.mktime(time.strptime(d2,"%Y-%m-%d %H:%M:%S")) -
               time.mktime(time.strptime(d1, "%Y-%m-%d %H:%M:%S")))

d1 = datetime.now()
d2 = datetime.now() + timedelta(days=1)
diff = diffdates(d1, d2)
Franck Dernoncourt
  • 77,520
  • 72
  • 342
  • 501
Prashant Gaur
  • 9,540
  • 10
  • 49
  • 71
2

Here's the one that is working for me.

from datetime import datetime

date_format = "%H:%M:%S"

# You could also pass datetime.time object in this part and convert it to string.
time_start = str('09:00:00') 
time_end = str('18:00:00')

# Then get the difference here.    
diff = datetime.strptime(time_end, date_format) - datetime.strptime(time_start, date_format)

# Get the time in hours i.e. 9.60, 8.5
result = diff.seconds / 3600;

Hope this helps!

mr_nobody
  • 356
  • 2
  • 4
2

Another approach is to use timestamp values:

end_time.timestamp() - start_time.timestamp()
Pei
  • 11,452
  • 5
  • 41
  • 45
0

By reading the source code, I came to a conclusion: the time difference cannot be obtained by .seconds:

@property
def seconds(self):
    """seconds"""
    return self._seconds

# in the `__new__`, you can find the `seconds` is modulo by the total number of seconds in a day
def __new__(cls, days=0, seconds=0, microseconds=0,
            milliseconds=0, minutes=0, hours=0, weeks=0):
    seconds += minutes*60 + hours*3600
    # ...
    if isinstance(microseconds, float):
        microseconds = round(microseconds + usdouble)
        seconds, microseconds = divmod(microseconds, 1000000)
        # ! 
        days, seconds = divmod(seconds, 24*3600)
        d += days
        s += seconds
    else:
        microseconds = int(microseconds)
        seconds, microseconds = divmod(microseconds, 1000000)
        # ! 
        days, seconds = divmod(seconds, 24*3600)
        d += days
        s += seconds
        microseconds = round(microseconds + usdouble)
    # ...

total_seconds can get an accurate difference between the two times

def total_seconds(self):
    """Total seconds in the duration."""
    return ((self.days * 86400 + self.seconds) * 10**6 +
        self.microseconds) / 10**6

in conclusion:

from datetime import datetime
dt1 = datetime.now()
dt2 = datetime.now()

print((dt2 - dt1).total_seconds())
crayon
  • 147
  • 1
  • 3