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
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 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)
Method 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
Method 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'
Method 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()
Method 5
Just use strftime 🙂
Something like that:
my_date = datetime.datetime(2013, 1, 7, 10, 31, 34, 243366, tzinfo=<UTC>)
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
Method 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)
Method 7
# 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'
Method 8
An alternative for this (older) question is to create a relative time from a timedelta converted to seconds. This can be accomplished using the time.gmtime(...) method that accepts seconds since the epoch:
>>> 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() so the difference can be truncated to any units, as needed. …)
Notably, this technique is also a great way to tell if your current time zone is actually in daylight savings time or not. (It provides an offset of 0 or 1 hours meaning it can be interpreted basically as a boolean.)
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'
This can be rendered to a method is_standard_time(...) where 1 means true and 0 means false.
Method 9
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.
Method 10
datetime.timedelta(hours=1, minutes=10) #python 2.7
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0