# Getting human-readable time interval strings

Here’s a neat little problem that came up yesterday. We’ve got some code using this common idiom to time a function call:

```start_time = time.time()
do_something_long_running()
end_time = time.time()

print "It took {} seconds to execute this".format(end_time - start_time)
```

We want to make the elapsed time in seconds more human-readable. The first thing we can do is use the string-format mini language to round the number to two decimal points:

```start_time = time.time()
do_something_long_running()
end_time = time.time()

print "It took {:.2f} seconds to execute this".format(end_time - start_time)
```

This is better! But for values that last longer than a few minutes, just displaying seconds is not particularly human friendly. What about minutes?

```start_time = time.time()
do_something_long_running()
end_time = time.time()
print "It took {} minutes to execute this".format((end_time - start_time) / 60.)

```

Well now we’ve just pushed the problem out to the next unit mark. So how about hours?

```start_time = time.time()
do_something_long_running()
end_time = time.time()

print "It took {} hours to execute this".format((end_time - start_time) / 3600.)
```

Great! But for function calls that cost in the range of a few seconds to a few minutes, all the significant digits get swallowed up in the rounding to hours. What we want is a nice, constant, `H:MM:SS.SS` format that can be easy to search against in log files and gives human-friendly reading. Similar to what we do above with dividing seconds by 60 to get minutes, and by 3600 (60 * 60) to get hours, we can write a function that does it all for us. We need to do an extra trick with the modulo operator, but otherwise this is straightforward:

```def hms_string(sec_elapsed):
h = int(sec_elapsed / (60 * 60))
m = int((sec_elapsed % (60 * 60)) / 60)
s = sec_elapsed % 60.
return "{}:{:>02}:{:>05.2f}".format(h, m, s)
# End hms_string

start_time = time.time()
do_something_long_running()
end_time = time.time()
print "It took {} to execute this".format(hms_string(end_time - start_time))
```

And the hms_string function could work with a `datetime.timedelta` as well, just pass in `timedelta.total_seconds()` as the value to `hms_string`:

```start_time = datetime.datetime.now()
do_something_long_running()
end_time = datetime.datetime.now()
seconds_elapsed = (end_time - start_time).total_seconds()
print "It took {} to execute this".format(hms_string(seconds_elapsed))
```

I recommend you check out the string format mini-language’s documentation — you can do all sorts of interesting things with it.

## 5 thoughts on “Getting human-readable time interval strings”

1. dm says:

personally, I use this:

import timeit
execusionTime = timeit.Timer(setup=’from __main__ import do_something_long_running()
‘, stmt= do_something_long_running()
‘)
print execusionTime.timeit(1)

2. kimo says:

I have found that using the datetime module instead of time allows easy formatting of intervals by default.
start = datetime.datetime.now()
….
print datetime.datetime.now() – start # nicely formatted HH:MM:SS.00