[python] How do I convert seconds to hours, minutes and seconds?

I have a function that returns information in seconds, but I need to store that information in hours:minutes:seconds.

Is there an easy way to convert the seconds to this format in Python?

This question is related to python

The answer is


This is my quick trick:

from humanfriendly import format_timespan
secondsPassed = 1302
format_timespan(secondsPassed)
# '21 minutes and 42 seconds'

For more info Visit: https://humanfriendly.readthedocs.io/en/latest/#humanfriendly.format_timespan


If you need to get datetime.time value, you can use this trick:

my_time = (datetime(1970,1,1) + timedelta(seconds=my_seconds)).time()

You cannot add timedelta to time, but can add it to datetime.

UPD: Yet another variation of the same technique:

my_time = (datetime.fromordinal(1) + timedelta(seconds=my_seconds)).time()

Instead of 1 you can use any number greater than 0. Here we use the fact that datetime.fromordinal will always return datetime object with time component being zero.


You can divide seconds by 60 to get the minutes

import time
seconds = time.time()
minutes = seconds / 60
print(minutes)

When you divide it by 60 again, you will get the hours


The solutions above will work if you're looking to convert a single value for "seconds since midnight" on a date to a datetime object or a string with HH:MM:SS, but I landed on this page because I wanted to do this on a whole dataframe column in pandas. If anyone else is wondering how to do this for more than a single value at a time, what ended up working for me was:

 mydate='2015-03-01'
 df['datetime'] = datetime.datetime(mydate) + \ 
                  pandas.to_timedelta(df['seconds_since_midnight'], 's')

In my case I wanted to achieve format "HH:MM:SS.fff". I solved it like this:

timestamp = 28.97000002861023
str(datetime.fromtimestamp(timestamp)+timedelta(hours=-1)).split(' ')[1][:12]
'00:00:28.970'

I can hardly name that an easy way (at least I can't remember the syntax), but it is possible to use time.strftime, which gives more control over formatting:

from time import strftime
from time import gmtime

strftime("%H:%M:%S", gmtime(666))
'00:11:06'

strftime("%H:%M:%S", gmtime(60*60*24))
'00:00:00'

gmtime is used to convert seconds to special tuple format that strftime() requires.

Note: Truncates after 23:59:59


hours (h) calculated by floor division (by //) of seconds by 3600 (60 min/hr * 60 sec/min)

minutes (m) calculated by floor division of remaining seconds (remainder from hour calculation, by %) by 60 (60 sec/min)

similarly, seconds (s) by remainder of hour and minutes calculation.

Rest is just string formatting!

def hms(seconds):
    h = seconds // 3600
    m = seconds % 3600 // 60
    s = seconds % 3600 % 60
    return '{:02d}:{:02d}:{:02d}'.format(h, m, s)

print(hms(7500))  # Should print 02h05m00s

dateutil.relativedelta is convenient if you need to access hours, minutes and seconds as floats as well. datetime.timedelta does not provide a similar interface.

from dateutil.relativedelta import relativedelta
rt = relativedelta(seconds=5440)
print(rt.seconds)
print('{:02d}:{:02d}:{:02d}'.format(
    int(rt.hours), int(rt.minutes), int(rt.seconds)))

Prints

40.0
01:30:40

Using datetime:

With the ':0>8' format:

from datetime import timedelta

"{:0>8}".format(str(timedelta(seconds=66)))
# Result: '00:01:06'

"{:0>8}".format(str(timedelta(seconds=666777)))
# Result: '7 days, 17:12:57'

"{:0>8}".format(str(timedelta(seconds=60*60*49+109)))
# Result: '2 days, 1:01:49'

Without the ':0>8' format:

"{}".format(str(timedelta(seconds=66)))
# Result: '00:01:06'

"{}".format(str(timedelta(seconds=666777)))
# Result: '7 days, 17:12:57'

"{}".format(str(timedelta(seconds=60*60*49+109)))
# Result: '2 days, 1:01:49'

Using time:

from time import gmtime
from time import strftime

# NOTE: The following resets if it goes over 23:59:59!

strftime("%H:%M:%S", gmtime(125))
# Result: '00:02:05'

strftime("%H:%M:%S", gmtime(60*60*24-1))
# Result: '23:59:59'

strftime("%H:%M:%S", gmtime(60*60*24))
# Result: '00:00:00'

strftime("%H:%M:%S", gmtime(666777))
# Result: '17:12:57'
# Wrong


division = 3623 // 3600 #to hours
division2 = 600 // 60 #to minutes
print (division) #write hours
print (division2) #write minutes

PS My code is unprofessional


This is how I got it.

def sec2time(sec, n_msec=3):
    ''' Convert seconds to 'D days, HH:MM:SS.FFF' '''
    if hasattr(sec,'__len__'):
        return [sec2time(s) for s in sec]
    m, s = divmod(sec, 60)
    h, m = divmod(m, 60)
    d, h = divmod(h, 24)
    if n_msec > 0:
        pattern = '%%02d:%%02d:%%0%d.%df' % (n_msec+3, n_msec)
    else:
        pattern = r'%02d:%02d:%02d'
    if d == 0:
        return pattern % (h, m, s)
    return ('%d days, ' + pattern) % (d, h, m, s)

Some examples:

$ sec2time(10, 3)
Out: '00:00:10.000'

$ sec2time(1234567.8910, 0)
Out: '14 days, 06:56:07'

$ sec2time(1234567.8910, 4)
Out: '14 days, 06:56:07.8910'

$ sec2time([12, 345678.9], 3)
Out: ['00:00:12.000', '4 days, 00:01:18.900']

By using the divmod() function, which does only a single division to produce both the quotient and the remainder, you can have the result very quickly with only two mathematical operations:

m, s = divmod(seconds, 60)
h, m = divmod(m, 60)

And then use string formatting to convert the result into your desired output:

print('{:d}:{:02d}:{:02d}'.format(h, m, s)) # Python 3
print(f'{h:d}:{m:02d}:{s:02d}') # Python 3.6+

The following set worked for me.

def sec_to_hours(seconds):
    a=str(seconds//3600)
    b=str((seconds%3600)//60)
    c=str((seconds%3600)%60)
    d=["{} hours {} mins {} seconds".format(a, b, c)]
    return d


print(sec_to_hours(10000))
# ['2 hours 46 mins 40 seconds']

print(sec_to_hours(60*60*24+105))
# ['24 hours 1 mins 45 seconds']