Format timedelta to string

后端 未结 28 1692
春和景丽
春和景丽 2020-11-22 03:57

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 cl

相关标签:
28条回答
  • 2020-11-22 04:01
    >>> 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.

    0 讨论(0)
  • 2020-11-22 04:01

    I continued from MarredCheese's answer and added year, month, millicesond and microsecond

    all numbers are formatted to integer except for second, thus the fraction of a second can be customized.

    @kfmfe04 asked for fraction of a second so I posted this solution

    In the main there are some examples.

    from string import Formatter
    from datetime import timedelta
    
    def strfdelta(tdelta, fmt='{D:02}d {H:02}h {M:02}m {S:02.0f}s', inputtype='timedelta'):
        """Convert a datetime.timedelta object or a regular number to a custom-
        formatted string, just like the stftime() method does for datetime.datetime
        objects.
    
        The fmt argument allows custom formatting to be specified.  Fields can 
        include seconds, minutes, hours, days, and weeks.  Each field is optional.
    
        Some examples:
            '{D:02}d {H:02}h {M:02}m {S:02.0f}s' --> '05d 08h 04m 02s' (default)
            '{W}w {D}d {H}:{M:02}:{S:02.0f}'     --> '4w 5d 8:04:02'
            '{D:2}d {H:2}:{M:02}:{S:02.0f}'      --> ' 5d  8:04:02'
            '{H}h {S:.0f}s'                       --> '72h 800s'
    
        The inputtype argument allows tdelta to be a regular number instead of the  
        default, which is a datetime.timedelta object.  Valid inputtype strings: 
            's', 'seconds', 
            'm', 'minutes', 
            'h', 'hours', 
            'd', 'days', 
            'w', 'weeks'
        """
    
        # Convert tdelta to integer seconds.
        if inputtype == 'timedelta':
            remainder = tdelta.total_seconds()
        elif inputtype in ['s', 'seconds']:
            remainder = float(tdelta)
        elif inputtype in ['m', 'minutes']:
            remainder = float(tdelta)*60
        elif inputtype in ['h', 'hours']:
            remainder = float(tdelta)*3600
        elif inputtype in ['d', 'days']:
            remainder = float(tdelta)*86400
        elif inputtype in ['w', 'weeks']:
            remainder = float(tdelta)*604800
    
        f = Formatter()
        desired_fields = [field_tuple[1] for field_tuple in f.parse(fmt)]
        possible_fields = ('Y','m','W', 'D', 'H', 'M', 'S', 'mS', 'µS')
        constants = {'Y':86400*365.24,'m': 86400*30.44 ,'W': 604800, 'D': 86400, 'H': 3600, 'M': 60, 'S': 1, 'mS': 1/pow(10,3) , 'µS':1/pow(10,6)}
        values = {}
        for field in possible_fields:
            if field in desired_fields and field in constants:
                Quotient, remainder = divmod(remainder, constants[field])
                values[field] = int(Quotient) if field != 'S' else Quotient + remainder
        return f.format(fmt, **values)
    
    if __name__ == "__main__":
        td = timedelta(days=717, hours=3, minutes=5, seconds=8, microseconds=3549)
        print(strfdelta(td,'{Y} years {m} months {W} weeks {D} days {H:02}:{M:02}:{S:02}'))  
        print(strfdelta(td,'{m} months {W} weeks {D} days {H:02}:{M:02}:{S:02.4f}'))  
        td = timedelta( seconds=8, microseconds=8549)
        print(strfdelta(td,'{S} seconds {mS} milliseconds {µS} microseconds'))  
        print(strfdelta(td,'{S:.0f} seconds {mS} milliseconds {µS} microseconds'))  
        print(strfdelta(pow(10,7),inputtype='s'))
    

    Output:

    1 years 11 months 2 weeks 3 days 01:09:56.00354900211096
    23 months 2 weeks 3 days 00:12:20.0035
    8.008549 seconds 8 milliseconds 549 microseconds
    8 seconds 8 milliseconds 549 microseconds
    115d 17h 46m 40s
    
    0 讨论(0)
  • 2020-11-22 04:02
    from django.utils.translation import ngettext
    
    def localize_timedelta(delta):
        ret = []
        num_years = int(delta.days / 365)
        if num_years > 0:
            delta -= timedelta(days=num_years * 365)
            ret.append(ngettext('%d year', '%d years', num_years) % num_years)
    
        if delta.days > 0:
            ret.append(ngettext('%d day', '%d days', delta.days) % delta.days)
    
        num_hours = int(delta.seconds / 3600)
        if num_hours > 0:
            delta -= timedelta(hours=num_hours)
            ret.append(ngettext('%d hour', '%d hours', num_hours) % num_hours)
    
        num_minutes = int(delta.seconds / 60)
        if num_minutes > 0:
            ret.append(ngettext('%d minute', '%d minutes', num_minutes) % num_minutes)
    
        return ' '.join(ret)
    

    This will produce:

    >>> from datetime import timedelta
    >>> localize_timedelta(timedelta(days=3660, minutes=500))
    '10 years 10 days 8 hours 20 minutes'
    
    0 讨论(0)
  • 2020-11-22 04:02

    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>
    
    0 讨论(0)
  • 2020-11-22 04:03

    If you already have a timedelta obj then just convert that obj into string. Remove the last 3 characters of the string and print. This will truncate the seconds part and print the rest of it in the format Hours:Minutes.

    t = str(timedeltaobj) 
    
    print t[:-3]
    
    0 讨论(0)
  • 2020-11-22 04:05

    If you happen to have IPython in your packages (you should), it has (up to now, anyway) a very nice formatter for durations (in float seconds). That is used in various places, for example by the %%time cell magic. I like the format it produces for short durations:

    >>> from IPython.core.magics.execution import _format_time
    >>> 
    >>> for v in range(-9, 10, 2):
    ...     dt = 1.25 * 10**v
    ...     print(_format_time(dt))
    
    1.25 ns
    125 ns
    12.5 µs
    1.25 ms
    125 ms
    12.5 s
    20min 50s
    1d 10h 43min 20s
    144d 16h 13min 20s
    14467d 14h 13min 20s
    
    0 讨论(0)
提交回复
热议问题