Convert a timedelta to days, hours and minutes

PythonTimedelta

Python Problem Overview


I've got a timedelta. I want the days, hours and minutes from that - either as a tuple or a dictionary... I'm not fussed.

I must have done this a dozen times in a dozen languages over the years but Python usually has a simple answer to everything so I thought I'd ask here before busting out some nauseatingly simple (yet verbose) mathematics.

Mr Fooz raises a good point.

I'm dealing with "listings" (a bit like ebay listings) where each one has a duration. I'm trying to find the time left by doing when_added + duration - now

Am I right in saying that wouldn't account for DST? If not, what's the simplest way to add/subtract an hour?

Python Solutions


Solution 1 - Python

If you have a datetime.timedelta value td, td.days already gives you the "days" you want. timedelta values keep fraction-of-day as seconds (not directly hours or minutes) so you'll indeed have to perform "nauseatingly simple mathematics", e.g.:

def days_hours_minutes(td):
    return td.days, td.seconds//3600, (td.seconds//60)%60

Solution 2 - Python

This is a bit more compact, you get the hours, minutes and seconds in two lines.

days = td.days
hours, remainder = divmod(td.seconds, 3600)
minutes, seconds = divmod(remainder, 60)
# If you want to take into account fractions of a second
seconds += td.microseconds / 1e6

Solution 3 - Python

days, hours, minutes = td.days, td.seconds // 3600, td.seconds // 60 % 60

As for DST, I think the best thing is to convert both datetime objects to seconds. This way the system calculates DST for you.

>>> m13 = datetime(2010, 3, 13, 8, 0, 0)  # 2010 March 13 8:00 AM
>>> m14 = datetime(2010, 3, 14, 8, 0, 0)  # DST starts on this day, in my time zone
>>> mktime(m14.timetuple()) - mktime(m13.timetuple())     # difference in seconds
82800.0
>>> _/3600                                                # convert to hours
23.0

Solution 4 - Python

I don't understand

days, hours, minutes = td.days, td.seconds // 3600, td.seconds // 60 % 60

how about this

days, hours, minutes = td.days, td.seconds // 3600, td.seconds % 3600 / 60.0

You get minutes and seconds of a minute as a float.

Solution 5 - Python

For all coming along and searching for an implementation:

The above posts are related to datetime.timedelta, which is sadly not having properties for hours and seconds. So far it was not mentioned, that there is a package, which is having these. You can find it here:

Example - Calculation:

>>> import timedelta

>>> td = timedelta.Timedelta(days=2, hours=2)

# init from datetime.timedelta
>>> td = timedelta.Timedelta(datetime1 - datetime2)

Example - Properties:

>>> td = timedelta.Timedelta(days=2, hours=2)
>>> td.total.seconds
180000
>>> td.total.minutes
3000
>>> td.total.hours
50
>>> td.total.days
2

I hope this could help someone...

Solution 6 - Python

I used the following:

delta = timedelta()
totalMinute, second = divmod(delta.seconds, 60)
hour, minute = divmod(totalMinute, 60)
print(f"{hour}h{minute:02}m{second:02}s")

Solution 7 - Python

I found the easiest way is using str(timedelta). It will return a sting formatted like 3 days, 21:06:40.001000, and you can parse hours and minutes using simple string operations or regular expression.

Solution 8 - Python

Here is a little function I put together to do this right down to microseconds:

def tdToDict(td:datetime.timedelta) -> dict:
    def __t(t, n):
        if t < n: return (t, 0)
        v = t//n
        return (t -  (v * n), v)
    (s, h) = __t(td.seconds, 3600)
    (s, m) = __t(s, 60)    
    (micS, milS) = __t(td.microseconds, 1000)

    return {
         'days': td.days
        ,'hours': h
        ,'minutes': m
        ,'seconds': s
        ,'milliseconds': milS
        ,'microseconds': micS
    }

Here is a version that returns a tuple:

# usage: (_d, _h, _m, _s, _mils, _mics) = tdTuple(td)
def tdTuple(td:datetime.timedelta) -> tuple:
    def _t(t, n):
        if t < n: return (t, 0)
        v = t//n
        return (t -  (v * n), v)
    (s, h) = _t(td.seconds, 3600)
    (s, m) = _t(s, 60)    
    (mics, mils) = _t(td.microseconds, 1000)
    return (td.days, h, m, s, mics, mils)

Solution 9 - Python

While pandas.Timedelta does not provide these attributes directly, it indeed provide a method called total_seconds, based on which days, hours, and minutes can be easily derived:

import pandas as pd
td = pd.Timedelta("2 days 12:30:00")
minutes = td.total_seconds()/60
hours = minutes/60
days = hours/ 24
print(minutes, hours, days)

Solution 10 - Python

This is another possible approach, though a bit wordier than those already mentioned. It maybe isn't the best approach for this scenario but it is handy to be able to obtain your time duration in a specific unit that isn't stored within the object (weeks, hours, minutes, milliseconds) and without having to remember or calculate conversion factors.

from datetime import timedelta
one_hour = timedelta(hours=1)
one_minute = timedelta(minutes=1)
print(one_hour/one_minute)  # Yields 60.0

> I've got a timedelta. I want the days, hours and minutes from that - either as a tuple or a dictionary... I'm not fussed.

in_time_delta = timedelta(days=2, hours=18, minutes=30)
td_d = timedelta(days=1)
td_h = timedelta(hours=1)
td_m = timedelta(minutes=1)
dmh_list = [in_time_delta.days,
            (in_time_delta%td_d)//td_h,
            (in_time_delta%td_h)//td_m]

Which should assign [2, 18, 30] to dmh_list

Solution 11 - Python

If using pandas (at least version >1.0), the Timedelta class has a components attribute that returns a named tuple with all the fields nicely laid out.

e.g.

import pandas as pd
delta = pd.Timestamp("today") - pd.Timestamp("2022-03-01")
print(delta.components)

Solution 12 - Python

timedeltas have a days and seconds attribute .. you can convert them yourself with ease.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionOliView Question on Stackoverflow
Solution 1 - PythonAlex MartelliView Answer on Stackoverflow
Solution 2 - PythonmberacocheaView Answer on Stackoverflow
Solution 3 - PythonJason OrendorffView Answer on Stackoverflow
Solution 4 - PythoncampbellView Answer on Stackoverflow
Solution 5 - PythonSiL3NC3View Answer on Stackoverflow
Solution 6 - PythonMathieu CAROFFView Answer on Stackoverflow
Solution 7 - PythonDaliang LYUView Answer on Stackoverflow
Solution 8 - PythonTimothy C. QuinnView Answer on Stackoverflow
Solution 9 - PythonFei YaoView Answer on Stackoverflow
Solution 10 - PythonjslataneView Answer on Stackoverflow
Solution 11 - PythonAdrianView Answer on Stackoverflow
Solution 12 - PythonJochen RitzelView Answer on Stackoverflow