Format timedelta to string

后端 未结 28 2032
春和景丽
春和景丽 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

    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
    

提交回复
热议问题