Convert seconds to hh:mm:ss in Python

169,423

Solution 1

I can't believe any of the many answers gives what I'd consider the "one obvious way to do it" (and I'm not even Dutch...!-) -- up to just below 24 hours' worth of seconds (86399 seconds, specifically):

>>> import time
>>> time.strftime('%H:%M:%S', time.gmtime(12345))
'03:25:45'

Doing it in a Django template's more finicky, since the time filter supports a funky time-formatting syntax (inspired, I believe, from PHP), and also needs the datetime module, and a timezone implementation such as pytz, to prep the data. For example:

>>> from django import template as tt
>>> import pytz
>>> import datetime
>>> tt.Template('{{ x|time:"H:i:s" }}').render(
...     tt.Context({'x': datetime.datetime.fromtimestamp(12345, pytz.utc)}))
u'03:25:45'

Depending on your exact needs, it might be more convenient to define a custom filter for this formatting task in your app.

Solution 2

>>> a = datetime.timedelta(seconds=65)
datetime.timedelta(0, 65)
>>> str(a)
'0:01:05'

Solution 3

Read up on the datetime module.

SilentGhost's answer has the details my answer leaves out and is reposted here:

>>> a = datetime.timedelta(seconds=65)
datetime.timedelta(0, 65)
>>> str(a)
'0:01:05'

Solution 4

Code that does what was requested, with examples, and showing how cases he didn't specify are handled:

def format_seconds_to_hhmmss(seconds):
    hours = seconds // (60*60)
    seconds %= (60*60)
    minutes = seconds // 60
    seconds %= 60
    return "%02i:%02i:%02i" % (hours, minutes, seconds)
def format_seconds_to_mmss(seconds):
    minutes = seconds // 60
    seconds %= 60
    return "%02i:%02i" % (minutes, seconds)
minutes = 60
hours = 60*60
assert format_seconds_to_mmss(7*minutes + 30) == "07:30"
assert format_seconds_to_mmss(15*minutes + 30) == "15:30"
assert format_seconds_to_mmss(1000*minutes + 30) == "1000:30"
assert format_seconds_to_hhmmss(2*hours + 15*minutes + 30) == "02:15:30"
assert format_seconds_to_hhmmss(11*hours + 15*minutes + 30) == "11:15:30"
assert format_seconds_to_hhmmss(99*hours + 15*minutes + 30) == "99:15:30"
assert format_seconds_to_hhmmss(500*hours + 15*minutes + 30) == "500:15:30"

You can--and probably should--store this as a timedelta rather than an int, but that's a separate issue and timedelta doesn't actually make this particular task any easier.

Solution 5

You can calculate the number of minutes and hours from the number of seconds by simple division:

seconds = 12345
minutes = seconds // 60
hours = minutes // 60
print "%02d:%02d:%02d" % (hours, minutes % 60, seconds % 60)
print "%02d:%02d" % (minutes, seconds % 60)

Here // is Python's integer division.

Share:
169,423
Admin
Author by

Admin

Updated on July 08, 2022

Comments

  • Admin
    Admin 6 months

    How do I convert an int (number of seconds) to the formats mm:ss or hh:mm:ss?

    I need to do this with Python code (and if possible in a Django template).

  • Guðmundur H
    Guðmundur H over 13 years
    minutes is modulo 60, so it's always < 60, so hours == 0...
  • Glenn Maynard
    Glenn Maynard over 13 years
    h:mm:sss isn't hh:mm:ss.
  • Matt Howell
    Matt Howell over 13 years
    @sth: SilentGhost has the deets.
  • Glenn Maynard
    Glenn Maynard over 13 years
    I don't think anything in datetime does what he wants. There's nothing like timedelta.strftime, so even if he stores his "number of seconds" as a timedelta (which he probably should), he'd still have to do the formatting himself. Converting it to a time would be a hack, since he does seem to have an amount of time (timedelta) and not a time of day (time).
  • Matt Howell
    Matt Howell over 13 years
    @Glenn: What's wrong with the str() representation?
  • SilentGhost
    SilentGhost over 13 years
    @Glenn: from the question it's quite clear that formatting requirement is rather fluid. And it's much easier to just convert to string and be happy with h:mm:ss then to multiply dirty hacks trying to get hh:mm:ss.
  • Glenn Maynard
    Glenn Maynard over 13 years
    It doesn't answer his question, or offer anything that would lead him to a good answer to his question--at best you'd have to manually prepend a 0 or strip off "0:", which isn't a good solution at all (depends on timedelta.__str__ behavior which isn't specified anywhere as far as I know, so it could change). So, yes.
  • Glenn Maynard
    Glenn Maynard over 13 years
    His question doesn't look fluid to me; it asks how to convert seconds to two specific formats, and almost everyone is responding with answers that simply don't do what he asked. Formatting this as he asked does not require anything approaching a hack.
  • Matt Howell
    Matt Howell over 13 years
    @Glenn: Dude, you're killing me from up on your idealistic high horse there. It does answer his question, even if it's not the model of perfection. (Manually having to append or prepend a "0" is not exactly an onerous burden.)
  • Glenn Maynard
    Glenn Maynard over 13 years
    He didn't say "format it something like this", he gave specific formats. I can't count the times I've formatted that way. Editing the string means you're depending on the specific behavior of timedelta's string formatting (if s[0:2] == "0:": ...), which is a bad idea. Maybe timedelta won't decide to format it as "h.mm.ss" in some locales now, but nothing says it can't in the future. It's simply a poor approach.
  • Admin
    Admin over 13 years
    You could shorten the calculations a bit with divmod.
  • SilentGhost
    SilentGhost over 13 years
    while it's a minor issue, which is possibly irrelevant for the OP time.strftime('%H:%M:%S', time.gmtime(864001)) return a nasty surprise.
  • SilentGhost
    SilentGhost over 13 years
    :) I don't think that my solution breaks down, it still provides the most-readable output, since OP hasn't participated in the discussion around here, I'm free to assume that that's exactly what he wants.
  • luator
    luator over 7 years
    I really like this, because it can cope with seconds > one day in a nice way and can even handle fractions of seconds: str(datetime.timedelta(seconds=1111111.11)) results in '12 days, 20:38:31.110000'. Exactly what I was looking for :)
  • Johannes Overmann
    Johannes Overmann over 3 years
    Nope. Not pythonic at all.
  • Peter Mortensen
    Peter Mortensen about 3 years
    Re "...any of the many answers": Do you mean "...none of the many answers"?
  • Granny Aching
    Granny Aching about 3 years
    As @AlexMartelli says, this doesn't work correctly if the number of seconds is more than a day. Also, str(datetime.timedelta(seconds=<number>)) is more elegant
  • milahu
    milahu over 2 years
    bugfix for secondsToStr: round milliseconds. replace "t*1000" with "round(t*1000)"
  • Merovex
    Merovex over 2 years
    So, I found this trying to solve the question, and this worked perfect for me. 1106236 seconds became "12 days, 19:17:16"
  • Null511
    Null511 over 2 years
    This is not only wasteful of memory, but also unpleasant to read and unlikely to serve any kind of performance improvement.
  • PaulMcG
    PaulMcG over 2 years
    Wow, it has been almost 10 years since I wrote this, sometimes frivolous answers can give some opportunities for learning some new things - thanks for the comment!
  • Skippy le Grand Gourou
    Skippy le Grand Gourou almost 2 years
    @GlennMaynard If "hh" is required, a simple .zfill(7) will take care of it.
  • Stefano
    Stefano about 1 year
    I don't get the 'dutch' thing :( Also, I'm not dutch either.
  • user3761340
    user3761340 6 months
    At the very least provide the specific code to implement the modulus. This answer come across to me as flippantly saying, "hey, there are 60 seconds in a minute--in case you didn't know."