Skip to content

Instantly share code, notes, and snippets.

@thatalextaylor
Last active November 5, 2023 22:48
Show Gist options
  • Star 33 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save thatalextaylor/7408395 to your computer and use it in GitHub Desktop.
Save thatalextaylor/7408395 to your computer and use it in GitHub Desktop.
Pretty print a time delta in Python in days, hours, minutes and seconds
def pretty_time_delta(seconds):
sign_string = '-' if seconds < 0 else ''
seconds = abs(int(seconds))
days, seconds = divmod(seconds, 86400)
hours, seconds = divmod(seconds, 3600)
minutes, seconds = divmod(seconds, 60)
if days > 0:
return '%s%dd%dh%dm%ds' % (sign_string, days, hours, minutes, seconds)
elif hours > 0:
return '%s%dh%dm%ds' % (sign_string, hours, minutes, seconds)
elif minutes > 0:
return '%s%dm%ds' % (sign_string, minutes, seconds)
else:
return '%s%ds' % (sign_string, seconds)
def pretty_time_delta(seconds):
seconds = int(seconds)
days, seconds = divmod(seconds, 86400)
hours, seconds = divmod(seconds, 3600)
minutes, seconds = divmod(seconds, 60)
if days > 0:
return '%dd%dh%dm%ds' % (days, hours, minutes, seconds)
elif hours > 0:
return '%dh%dm%ds' % (hours, minutes, seconds)
elif minutes > 0:
return '%dm%ds' % (minutes, seconds)
else:
return '%ds' % (seconds,)

I needed to print time deltas in a compact hours, minutes seconds format for log output. As an example try these on the Python console:

>>> pretty_time_delta(123)
'2m3s'
>>> pretty_time_delta(12345)
'3h25m45s'
>>> pretty_time_delta(1234567)
'14d6h56m7s'

It only displays to second precision and only displays up to hours as the largest unit. To convert a standard Python datetime.timedelta, use the total_seconds() method on your timedelta to convert to seconds. If all your calls come from standard Python datetime operations, you probably want to change line 3 to something like:

seconds = abs(int(seconds.total_seconds()))

The built-in string representation of a timedelta is also quite acceptable for most situations and also handles sub-second precision (see the last example):

>>> import datetime
>>> str(datetime.timedelta(seconds=123))
'0:02:03'
>>> str(datetime.timedelta(seconds=12345))
'3:25:45'
>>> str(datetime.timedelta(seconds=1234567))
'14 days, 6:56:07'
>>> str(datetime.timedelta(seconds=123.456789))
'0:02:03.456789'

The version included in python-pretty-time-delta-positive-only.py has the negative number handling stripped out for some slightly simpler code.

@MichaelBurge
Copy link

Stole this to track some machine learning code that's going to take about 5 hours to run. Thanks for publishing it!

@PeterBaker0
Copy link

Thanks - handy

@psprojectC
Copy link

psprojectC commented Aug 12, 2022

import inflect

grammar = inflect.engine()


def pretty_time_delta(seconds, lang: inflect.engine):
    if not seconds:
        return f"0 seconds"
    seconds = int(seconds)
    days, seconds = divmod(seconds, 86400)
    hours, seconds = divmod(seconds, 3600)
    minutes, seconds = divmod(seconds, 60)
    measures = (
        (days, "day"),
        (hours, "hour"),
        (minutes, "minute"),
        (seconds, "second"),
    )
    return lang.join(
        [f"{count} {lang.plural(noun, count)}" for (count, noun) in measures if count]
    )

Consider this implementation, it outputs a human readable string and ignores whatever is equal to 0, for example if you give it 7200 seconds it will say '2 hours', 7201 - '2 hours and 1 second', etc. Requires the inflect module.

@nickjvturner
Copy link

nickjvturner commented Feb 14, 2023

import inflect


def pretty_time_delta(seconds, lang=inflect.engine()):
    if not seconds:
        return f"0 seconds"
    seconds = int(seconds)
    days, seconds = divmod(seconds, 86400)
    hours, seconds = divmod(seconds, 3600)
    minutes, seconds = divmod(seconds, 60)
    measures = (
        (days, "day"),
        (hours, "hour"),
        (minutes, "minute"),
        (seconds, "second"),
    )
    return lang.join(
        [f"{count} {lang.plural(noun, count)}" for (count, noun) in measures if count]
    )

Consider this implementation, it outputs a human readable string and ignores whatever is equal to 0, for example if you give it 7200 seconds it will say '2 hours', 7201 - '2 hours and 1 second', etc. Requires the inflect module.

duration = 545.67

print(pretty_time_delta(duration))

9 minutes and 5 seconds

@mikbuch
Copy link

mikbuch commented Nov 5, 2023

This is great! Your function should be implemented in datetime, for real!

Based on your code, I created a similar function for the timedelta object from datatime. Here it is, along with a simple example: https://gist.github.com/mikbuch/6678247656cd8eee6b70af9486db3f20

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment