1

Looking for easiest way to calculate the difference between 2 python times and display the millisecond delta

I have 2 times

startTime = datetime.datetime.now().time()

do some stuff...

endTime= datetime.datetime.now().time()

This works fine and when I log the times out and I get something like this in my logs...

RequestStartTime = 08:56:19.188999

ResponseTime = 08:56:19.905999

When I try to simply subtract them like this

delta = endTime - startTime

I get the following error

unsupported operand type(s) for -: 'time' and 'time'

All I want to do is show the difference in microseconds and I can't figure it out

I want to show is 717000 ms

Mazdak
  • 105,000
  • 18
  • 159
  • 188
Stiley
  • 123
  • 2
  • 12

6 Answers6

4

If you just use the result of now(), and don't convert them to times, you can take the difference & extract the bits you want in the form you want; for example:

startTime = datetime.datetime.now()
endTime= datetime.datetime.now()
delta = endTime - startTime
print str(delta).split(":")[2]
Scott Hunter
  • 48,888
  • 12
  • 60
  • 101
  • 1
    you may get a wrong result during DST transitions. Use `utcnow()` + `.total_seconds()` or `time.monotonic()` (short intervals) instead. – jfs Sep 02 '15 at 16:14
  • This works great, thanks but now I am only getting microseconds. so for example when I have these 2 times like14:25:52.206000 and 14:25:55.539000 I get a difference of 333000 which is the microseconds but I am not getting the 3 seconds, (55 - 52), included in that. Is there an easy way to do that all in one fell swoop? – Stiley Sep 02 '15 at 18:27
  • I can do it as follows but seems this way is harder than it should be `seconds = str((endTime - startTime).seconds)` `microseconds = str((endTime - startTime).microseconds)` `infolog(seconds+"."+microseconds)` – Stiley Sep 02 '15 at 18:32
  • 1
    @Stiley: as I said above, you could use `seconds = (end_time - start_time).total_seconds()`, to get seconds including microseconds (as a fraction). To get milliseconds directly, use: `milliseconds = (end - start) / timedelta(milliseconds=1)` as shown in [my answer](http://stackoverflow.com/a/32358658/4279) – jfs Sep 04 '15 at 12:22
2

Try this:

from datetime import datetime, date

datetime.combine(date.today(), endTime) - datetime.combine(date.today(), startTime)

Hope this Helps.

Navneet
  • 4,543
  • 1
  • 19
  • 29
1

To measure the difference manually, you should use time.monotonic() instead.

If you don't care about leap seconds (~1s error once per year and a half) and you need to display the local time:

#!/usr/bin/env python3
from datetime import datetime, timedelta, timezone

start = datetime.now(timezone.utc).astimezone() # current local time
# print("RequestStartTime = %s" % start.time())
end = datetime.now(timezone.utc).astimezone()
diff_milliseconds = (end - start) / timedelta(milliseconds=1)
print("%.0f ms" % diff_milliseconds)

The code works fine around/during DST transitions.

Note: it is different from the code that uses just .now(). If you use .now() (no argument) then you get a naive datetime object that represents local time and in that case if a DST transition happens between start and end times then end - start returns a completely wrong result i.e., the code may be wrong by an hour approximately couple of times per year in some timezones.

jfs
  • 399,953
  • 195
  • 994
  • 1,670
0

the reason why you are getting an error is because class time does not support subtraction. You must turn time into miliseconds (int format) to subtract from one another.

instead of using datetime, use time

import time

def timenow():
    return int(round(time.time() * 1000))

startTime = timenow()
time.sleep(1)
endTime = timenow()

delta = endTime - startTime
print delta
taesu
  • 4,482
  • 4
  • 23
  • 41
0

The simplest solution would be to convert the datetime objects to timestamps and subtract those. If you use Python 3.3 or later you can simply do something along these lines

startTime = datetime.datetime.now(timezone.utc).timestamp()
...
endTime = datetime.datetime.now(timezone.utc).timestamp()

Then you can just subtract those.

In Python 2 you do not have the timestamp method available. One way around would be to use a timedelta object:

startTime = datetime.datetime.now(timezone.utc)
...
endTime = datetime.datetime.now(timezone.utc)
dt = (endTime - startTime).total_seconds()

A third option is to simply use raw timestamps with time.time() and subtract them to get the time interval in seconds and fraction of seconds.

To be extra safe you could use time.monotonic() as @Sebastian mentions.

fpierfed
  • 71
  • 5
  • you should call `time.time()` instead (`.now().timestamp()` may fail during DST transitions). Note: both results may be inaccurate due to ntp-adjustments or around a leap second. You could [use `time.monotonic()` in this case](http://stackoverflow.com/a/32358658/4279) – jfs Sep 02 '15 at 16:45
  • Excellent points, @Sebastian. I have updated my answer to use UTC. Of course the issue with leap second adjustment remains. – fpierfed Sep 02 '15 at 17:40
  • `utcnow().timestamp()` is wrong unless the local timezone has zero utc offset. `.microseconds` is wrong if the difference is larger than a second (you could use `.total_seconds()` instead) – jfs Sep 02 '15 at 17:42
  • @J.F.Sebastian: you are totally right about ```.microseconds```! I have changed my answer to reflect that, thank you. Could you please expand on why a difference in timestamps would be incorrect when using ```.utcnow```? Thanks – fpierfed Sep 02 '15 at 18:05
  • `.timestamp()` uses local timezone for naive datetime objects (that may make the absolute values wrong). Local timezone may have different utc offsets at different times (that makes the difference wrong) – jfs Sep 02 '15 at 18:08
  • @J.F.Sebastian you sir are right again! I have learned something today. Thanks – fpierfed Sep 02 '15 at 18:18
0

This is the best answer for this problem: https://stackoverflow.com/a/39651061/2686243

from datetime import datetime, date

duration = datetime.combine(date.min, end) - datetime.combine(date.min, beginning)
Community
  • 1
  • 1
Martin
  • 660
  • 10
  • 23