views:

8439

answers:

6

Hi, I'm a python newbie (2 weeks) and I'm having trouble formatting a datetime.timedelta object.

Here's what I'm trying to do. I have a list of objects and one of the members of the class of the object is a timedelta object that shows the duration of an event. I would like to display that duration in the format of hours:minutes.

I have tried a variety of methods for doing this and I'm having difficulty. My current approach is to add methods to the class for my objects that return hours and minutes. I can get the hours by dividing the timedelta.seconds by 3600 and rounding it. I'm having trouble with getting the remainder seconds and converting that to minutes.

By the way, I'm using Google AppEngine with DJango Templates for presentation.

If anyone can help or knows of a better way to resolve this, I would be very happy.

Thanks,

+3  A: 
>>> str(datetime.timedelta(hours=10.56))
10:33:36

>>> td = datetime.timedelta(hours=10.505) # any timedelta object
>>> ':'.join(str(td).split(':')[:2])
10:30

Passing the timedelta object to the str() function calls the same formatting code used if we simply type print td. Since you don't want the seconds, we can split the string by colons (3 parts) and put it back together with only the first 2 parts.

joeforker
Thanks for your answer joeforker, but I'm not sure I understand your response. I am getting a time delta by way of datetime - datetime. I don't know the hours. Plus, it looks like your example includes seconds, how would I remove that?
mawcs
Doesn't matter where you get the timedelta object, it will format the same.
joeforker
If it's longer than a day, it will format as e.g. "4 days, 8:00" after the split/join processing.
joeforker
A: 

Following Joe's example value above, I'd use the modulus arithmetic operator, thusly:

td = datetime.timedelta(hours=10.56)
td_str = "%d:%d" % (td.seconds/3600, td.seconds%3600/60)

Note that integer division in Python rounds down by default; if you want to be more explicit, use math.floor() or math.ceil() as appropriate.

UltraNurd
timedelta already knows how to format itself, as in 'print some_timedelta'.
joeforker
Yeah, but it can't accept an arbitrary format string, which is what Michael was asking.Although now that I think about it 3600 division mod makes the hours-seconds assumption which causes problems at leap seconds.
UltraNurd
Yeah, but he doesn't want an arbitrary format string, he wants almost exactly the default behaviour.
joeforker
Don't forget // for truncating division in Python 3000
joeforker
Ah, I've only be using up through 2.6.
UltraNurd
+10  A: 

You can just call the "str" method on the timedelta. Here's an example:

import datetime
start = datetime.datetime(2009,2,10,14,00)
end = datetime.datetime(2009,2,10,16,00)
delta = end-start
print str(delta)
# prints 2:00:00
Parand
More like calling the str() method with timedelta as its argument.
joeforker
A: 

Thanks everyone for your help. I took many of your ideas and put them together, let me know what you think.

I added two methods to the class like this:

def hours(self):
    retval = ""
    if self.totalTime:
        hoursfloat = self.totalTime.seconds / 3600
        retval = round(hoursfloat)
    return retval

def minutes(self):
    retval = ""
    if self.totalTime:
        minutesfloat = self.totalTime.seconds / 60
        hoursAsMinutes = self.hours() * 60
        retval = round(minutesfloat - hoursAsMinutes)
    return retval

In my django I used this (sum is the object and it is in a dictionary):

<td>{{ sum.0 }}</td>    
<td>{{ sum.1.hours|stringformat:"d" }}:{{ sum.1.minutes|stringformat:"#02.0d" }}</td>
mawcs
It's a bit long. I would suggest:def hhmm(self): return ':'.join(str(td).split(':')[:2])<td>{{ sum.1.hhmm }}</td>
joeforker
+9  A: 

As you know, you can get the seconds from a timedelta object by accessing the .seconds attribute.

You can convert that to hours and remainder by using a combination of modulo and subtraction:

# arbitrary number of seconds
s = 13420
# hours
hours = s // 3600 
# remaining seconds
s = s - (hours * 3600)
# minutes
minutes = s // 60
# remaining seconds
seconds = s - (minutes * 60)
# total time
print '%s:%s:%s' % (hours, minutes, seconds)
# result: 3:43:40

However, python provides the builtin function divmod() which allows us to simplify this code:

s = 13420
hours, remainder = divmod(s, 3600)
minutes, seconds = divmod(remainder, 60)
print '%s:%s:%s' % (hours, minutes, seconds)
# result: 3:43:40

Hope this helps!

John Fouhy
+2  A: 

My datetime.timedelta objects went greater than a day. So here is a further problem. All the discussion above assumes less than a day. A timedelta is actually a tuple of days, seconds and microseconds. The above discussion should use td.seconds as joe did, but if you have days it is NOT included in the seconds value.

I am getting a span of time between 2 datetimes and printing days and hours.

span = currentdt - previousdt print '%d,%d\n' % (span.days,span.seconds/3600)

catfishlar