Question or problem about Python programming:
I get a start_date like this:
from django.utils.timezone import utc import datetime start_date = datetime.datetime.utcnow().replace(tzinfo=utc) end_date = datetime.datetime.utcnow().replace(tzinfo=utc) duration = end_date - start_date
I get output like this:
datetime.timedelta(0, 5, 41038)
How do I convert this into normal time like the following?
10 minutes, 1 hour like this
How to solve the problem:
Solution 1:
There’s no built-in formatter for timedelta
objects, but it’s pretty easy to do it yourself:
days, seconds = duration.days, duration.seconds hours = days * 24 + seconds // 3600 minutes = (seconds % 3600) // 60 seconds = seconds % 60
Or, equivalently, if you’re in Python 2.7+ or 3.2+:
seconds = duration.total_seconds() hours = seconds // 3600 minutes = (seconds % 3600) // 60 seconds = seconds % 60
Now you can print it however you want:
'{} minutes, {} hours'.format(minutes, hours)
For example:
def convert_timedelta(duration): days, seconds = duration.days, duration.seconds hours = days * 24 + seconds // 3600 minutes = (seconds % 3600) // 60 seconds = (seconds % 60) return hours, minutes, seconds td = datetime.timedelta(2, 7743, 12345) hours, minutes, seconds = convert_timedelta(td) print '{} minutes, {} hours'.format(minutes, hours)
This will print:
9 minutes, 50 hours
If you want to get “10 minutes, 1 hour” instead of “10 minutes, 1 hours”, you need to do that manually too:
print '{} minute{}, {} hour{}'.format(minutes, 's' if minutes != 1 else '', hours, 's' if minutes != 1 else '')
Or you may want to write an english_plural
function to do the 's'
bits for you, instead of repeating yourself.
From your comments, it sounds like you actually want to keep the days separate. That’s even easier:
def convert_timedelta(duration): days, seconds = duration.days, duration.seconds hours = seconds // 3600 minutes = (seconds % 3600) // 60 seconds = (seconds % 60) return days, hours, minutes, seconds
If you want to convert this to a single value to store in a database, then convert that single value back to format it, do this:
def dhms_to_seconds(days, hours, minutes, seconds): return (((days * 24) + hours) * 60 + minutes) * 60 + seconds def seconds_to_dhms(seconds): days = seconds // (3600 * 24) hours = (seconds // 3600) % 24 minutes = (seconds // 60) % 60 seconds = seconds % 60 return days, hours, minutes, seconds
So, putting it together:
def store_timedelta_in_database(thingy, duration): seconds = dhms_to_seconds(*convert_timedelta(duration)) db.execute('INSERT INTO foo (thingy, duration) VALUES (?, ?)', thingy, seconds) db.commit() def print_timedelta_from_database(thingy): cur = db.execute('SELECT duration FROM foo WHERE thingy = ?', thingy) seconds = int(cur.fetchone()[0]) days, hours, minutes, seconds = seconds_to_dhms(seconds) print '{} took {} minutes, {} hours, {} days'.format(thingy, minutes, hours, days)
Solution 2:
A datetime.timedelta
corresponds to the difference between two dates, not a date itself. It’s only expressed in terms of days, seconds, and microseconds, since larger time units like months and years don’t decompose cleanly (is 30 days 1 month or 0.9677 months?).
If you want to convert a timedelta
into hours and minutes, you can use the total_seconds()
method to get the total number of seconds and then do some math:
x = datetime.timedelta(1, 5, 41038) # Interval of 1 day and 5.41038 seconds secs = x.total_seconds() hours = int(secs / 3600) minutes = int(secs / 60) % 60
Solution 3:
There is no need for custom helper functions if all we need is to print the string of the form [D day[s], ][H]H:MM:SS[.UUUUUU]
. timedelta object supports str()
operation that will do this. It works even in Python 2.6.
>>> from datetime import timedelta >>> timedelta(seconds=90136) datetime.timedelta(1, 3736) >>> str(timedelta(seconds=90136)) '1 day, 1:02:16'
Solution 4:
I don’t think it’s a good idea to caculate yourself.
If you just want a pretty output, just covert it into str
with str()
function or directly print()
it.
And if there’s further usage of the hours and minutes, you can parse it to datetime
object use datetime.strptime()
(and extract the time part with datetime.time()
mehtod), for example:
import datetime delta = datetime.timedelta(seconds=10000) time_obj = datetime.datetime.strptime(str(delta),'%H:%M:%S').time()
Solution 5:
Just use strftime ๐
Something like that:
my_date = datetime.datetime(2013, 1, 7, 10, 31, 34, 243366, tzinfo=) print(my_date.strftime("%Y, %d %B"))
After edited your question to format timedelta
, you could use:
def timedelta_tuple(timedelta_object): return timedelta_object.days, timedelta_object.seconds//3600, (timedelta_object.seconds//60)%60
Solution 6:
I defined own helper function to convert timedelta object to ‘HH:MM:SS’ format – only hours, minutes and seconds, without changing hours to days.
def format_timedelta(td): hours, remainder = divmod(td.total_seconds(), 3600) minutes, seconds = divmod(remainder, 60) hours, minutes, seconds = int(hours), int(minutes), int(seconds) if hours < 10: hours = '0%s' % int(hours) if minutes < 10: minutes = '0%s' % minutes if seconds < 10: seconds = '0%s' % seconds return '%s:%s:%s' % (hours, minutes, seconds)
Solution 7:
Do you want to print the date in that format? This is the Python documentation: http://docs.python.org/2/library/datetime.html#strftime-strptime-behavior
>>> a = datetime.datetime(2013, 1, 7, 10, 31, 34, 243366) >>> print a.strftime('%Y %d %B, %M:%S%p') >>> 2013 07 January, 31:34AM
For the timedelta:
>>> a = datetime.timedelta(0,5,41038) >>> print '%s seconds, %s microseconds' % (a.seconds, a.microseconds)
But please notice, you should make sure it has the related value. For the above cases, it doesn't have the hours and minute values, and you should calculate from the seconds.
Solution 8:
Another alternative for this (older) question:
import datetime import pytz import time pacific=pytz.timezone('US/Pacific') now=datetime.datetime.now() # pacific.dst(now).total_seconds() yields 3600 secs. [aka 1 hour] time.strftime("%-H", time.gmtime(pacific.dst(now).total_seconds())) '1'
The above is a good way to tell if your current time zone is actually in daylight savings time or not. (It provides an offset of 0 or 1.) Anyway, the real work is being done by time.strftime("%H:%M:%S", time.gmtime(36901))
which does work on the output of gmtime()
.
>>> time.strftime("%H:%M:%S",time.gmtime(36901)) # secs = 36901 '10:15:01'
And, that's it! (NOTE: Here's a link to format specifiers for time.strftime()
. ...)
Solution 9:
# Try this code from datetime import timedelta class TimeDelta(timedelta): def __str__(self): _times = super(TimeDelta, self).__str__().split(':') if "," in _times[0]: _hour = int(_times[0].split(',')[-1].strip()) if _hour: _times[0] += " hours" if _hour > 1 else " hour" else: _times[0] = _times[0].split(',')[0] else: _hour = int(_times[0].strip()) if _hour: _times[0] += " hours" if _hour > 1 else " hour" else: _times[0] = "" _min = int(_times[1]) if _min: _times[1] += " minutes" if _min > 1 else " minute" else: _times[1] = "" _sec = int(_times[2]) if _sec: _times[2] += " seconds" if _sec > 1 else " second" else: _times[2] = "" return ", ".join([i for i in _times if i]).strip(" ,").title()
# Test >>> str(TimeDelta(seconds=10)) '10 Seconds' >>> str(TimeDelta(seconds=60)) '01 Minute' >>> str(TimeDelta(seconds=90)) '01 Minute, 30 Seconds' >>> str(TimeDelta(seconds=3000)) '50 Minutes' >>> str(TimeDelta(seconds=3600)) '1 Hour' >>> str(TimeDelta(seconds=3690)) '1 Hour, 01 Minute, 30 Seconds' >>> str(TimeDelta(seconds=3660)) '1 Hour, 01 Minute' >>> str(TimeDelta(seconds=3630)) '1 Hour, 30 Seconds' >>> str(TimeDelta(seconds=3600*20)) '20 Hours' >>> str(TimeDelta(seconds=3600*20 + 3000)) '20 Hours, 50 Minutes' >>> str(TimeDelta(seconds=3600*20 + 3630)) '21 Hours, 30 Seconds' >>> str(TimeDelta(seconds=3600*20 + 3660)) '21 Hours, 01 Minute' >>> str(TimeDelta(seconds=3600*20 + 3690)) '21 Hours, 01 Minute, 30 Seconds' >>> str(TimeDelta(seconds=3600*24)) '1 Day' >>> str(TimeDelta(seconds=3600*24 + 10)) '1 Day, 10 Seconds' >>> str(TimeDelta(seconds=3600*24 + 60)) '1 Day, 01 Minute' >>> str(TimeDelta(seconds=3600*24 + 90)) '1 Day, 01 Minute, 30 Seconds' >>> str(TimeDelta(seconds=3600*24 + 3000)) '1 Day, 50 Minutes' >>> str(TimeDelta(seconds=3600*24 + 3600)) '1 Day, 1 Hour' >>> str(TimeDelta(seconds=3600*24 + 3630)) '1 Day, 1 Hour, 30 Seconds' >>> str(TimeDelta(seconds=3600*24 + 3660)) '1 Day, 1 Hour, 01 Minute' >>> str(TimeDelta(seconds=3600*24 + 3690)) '1 Day, 1 Hour, 01 Minute, 30 Seconds' >>> str(TimeDelta(seconds=3600*24*2)) '2 Days' >>> str(TimeDelta(seconds=3600*24*2 + 9999)) '2 Days, 2 Hours, 46 Minutes, 39 Seconds'
Solution 10:
datetime.timedelta(hours=1, minutes=10) #python 2.7