views:

2767

answers:

9

Hi,

Please, how to convert an int (number a seconds) to these formats: mm:ss or hh:mm:ss ?

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

Thank you very much ;-)

+3  A: 

Have you read up on the datetime module?

Edit/update: SilentGhost's answer has the details my answer leaves out. If you like this answer, +1 his as well (or instead). Reposted here:

>>> a = datetime.timedelta(seconds=65)
datetime.timedelta(0, 65)
>>> str(a)
'0:01:05'
bigmattyh
@sth: SilentGhost has the deets.
bigmattyh
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).
Glenn Maynard
@Glenn: What's wrong with the str() representation?
bigmattyh
@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`.
SilentGhost
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.
Glenn Maynard
A: 

Besides the fact that Python has built in support for dates and times (see bigmattyh's response), finding minutes or hours from seconds is easy:

minutes = seconds / 60
hours = minutes / 60

Now, when you want to display minutes or seconds, MOD them by 60 so that they will not be larger than 59

Ed Swangren
minutes is modulo 60, so it's always < 60, so hours == 0...
Guðmundur H
Oops, sorry, meant to do that step afterwards... will fix
Ed Swangren
A: 

Not being a python person but easiest without any libraries just:

total   = 3800
seconds = total % 60
total   = total - seconds
hours   = total / 3600
total   = total - (hours * 3600)
mins    = total / 60

Updated code, thanks sth

ba
This gives 200 hours for 3800 seconds...
sth
thanks sth, don't post untested code when you're tired has been noted :)
ba
We've all been there...
Glenn Maynard
+4  A: 

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 pythons integer division.

sth
Serously, use divmod.
unbeknown
A: 

Just be careful when dividing by 60: division between integers returns an integer -> 12/60 = 0 unless you import division from future. The following is copy and pasted from Python 2.6.2:

IDLE 2.6.2      
>>> 12/60
0
>>> from __future__ import division
>>> 12/60
0.20000000000000001
Francesco
+7  A: 
>>> a = datetime.timedelta(seconds=65)
datetime.timedelta(0, 65)
>>> str(a)
'0:01:05'
SilentGhost
h:mm:sss isn't hh:mm:ss.
Glenn Maynard
seriously? and it's worth downvote?
SilentGhost
@Glenn: It's pretty good... and if the OP wants to format it further, it's not exactly rocket science from here.
bigmattyh
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
i think you're just missing the point, OP needs number of seconds in **readable** format. that's what matters.
SilentGhost
@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.)
bigmattyh
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.
Glenn Maynard
lol such nerdrage in these comments..
Daniel T. Magnusson
+4  A: 

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.

Glenn Maynard
Voting down a clean, clear solution that gives exactly what was requested, complete with tests--a shining example of StackOverflow's voting system. Anyone care to fess up?
Glenn Maynard
+1: Nice, thorough, and flexible answer; and partly to counter the downvote. (Though I have no intention to weigh in on the debate of datetime vs this -- I assume the OP will say what he was hoping for soon enough.)
tom10
A rather more heated debate than I was looking for, myself, for such a basic question; there are better things to spend energy on...
Glenn Maynard
The double-slash is interpreted by the code-colorer as a comment. This seems to be wrong.
Robert L
You could shorten the calculations a bit with divmod.
unbeknown
+11  A: 

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.

Alex Martelli
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
Yep, only works up for one day -- as does your solution of course, which breaks down differently instead of "wrapping around", since `str(datetime.timedelta(seconds=86400))` says "1 day";-)
Alex Martelli
:) 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.
SilentGhost
A: 

If you use divmod, you are immune to different flavors of integer division:

# show time strings for 3800 seconds

# easy way to get mm:ss
print "%02d:%02d" % divmod(3800, 60)

# easy way to get hh:mm:ss
print "%02d:%02d:%02d" % \
    reduce(lambda ll,b : divmod(ll[0],b) + ll[1:],
        [(3800,),60,60])


# function to convert floating point number of seconds to 
# hh:mm:ss.sss
def secondsToStr(t):
    return "%02d:%02d:%02d.%03d" % \
        reduce(lambda ll,b : divmod(ll[0],b) + ll[1:],
            [(t*1000,),1000,60,60])

print secondsToStr(3800.123)

Prints:

63:20
01:03:20
01:03:20.123
Paul McGuire