How can I produce a human readable difference when subtracting two UNIX timestamps using Python?

后端 未结 7 973
無奈伤痛
無奈伤痛 2020-12-23 19:39

This question is similar to this question about subtracting dates with Python, but not identical. I\'m not dealing with strings, I have to figure out the difference between

相关标签:
7条回答
  • 2020-12-23 19:50

    Here's a shorter one for interval in seconds and within a day (t<86400). Useful if you work with unix timestamps (seconds since epoch, UTC).

    t = 45678
    print('%d hours, %d minutes, %d seconds' % (t//3600, t%3600//60, t%60))
    

    May be extended further (t//86400, ...).

    0 讨论(0)
  • 2020-12-23 19:51

    Old question, but I personally like this approach most:

    import datetime
    import math
    
    def human_time(*args, **kwargs):
        secs  = float(datetime.timedelta(*args, **kwargs).total_seconds())
        units = [("day", 86400), ("hour", 3600), ("minute", 60), ("second", 1)]
        parts = []
        for unit, mul in units:
            if secs / mul >= 1 or mul == 1:
                if mul > 1:
                    n = int(math.floor(secs / mul))
                    secs -= n * mul
                else:
                    n = secs if secs != int(secs) else int(secs)
                parts.append("%s %s%s" % (n, unit, "" if n == 1 else "s"))
        return ", ".join(parts)
    
    human_time(seconds=3721)
    # -> "1 hour, 2 minutes, 1 second"
    

    If you want to separate the seconds part with an "and" do:

    "%s and %s" % tuple(human_time(seconds=3721).rsplit(", ", 1))
    # -> "1 hour, 2 minutes and 1 second"
    
    0 讨论(0)
  • 2020-12-23 19:59

    A little improvement over @Schnouki's solution with a single line list comprehension. Also displays the plural in case of plural entities (like hours)

    Import relativedelta

    >>> from dateutil.relativedelta import relativedelta
    

    A lambda function

    >>> attrs = ['years', 'months', 'days', 'hours', 'minutes', 'seconds']
    >>> human_readable = lambda delta: ['%d %s' % (getattr(delta, attr), attr if getattr(delta, attr) > 1 else attr[:-1]) 
    ...     for attr in attrs if getattr(delta, attr)]
    

    Example usage:

    >>> human_readable(relativedelta(minutes=125))
    ['2 hours', '5 minutes']
    >>> human_readable(relativedelta(hours=(24 * 365) + 1))
    ['365 days', '1 hour']
    
    0 讨论(0)
  • 2020-12-23 20:02
    def humanize_time(amount, units = 'seconds'):    
    
        def process_time(amount, units):
    
            INTERVALS = [   1, 60, 
                            60*60, 
                            60*60*24, 
                            60*60*24*7, 
                            60*60*24*7*4, 
                            60*60*24*7*4*12, 
                            60*60*24*7*4*12*100,
                            60*60*24*7*4*12*100*10]
            NAMES = [('second', 'seconds'),
                     ('minute', 'minutes'),
                     ('hour', 'hours'),
                     ('day', 'days'),
                     ('week', 'weeks'),
                     ('month', 'months'),
                     ('year', 'years'),
                     ('century', 'centuries'),
                     ('millennium', 'millennia')]
    
            result = []
    
            unit = map(lambda a: a[1], NAMES).index(units)
            # Convert to seconds
            amount = amount * INTERVALS[unit]
    
            for i in range(len(NAMES)-1, -1, -1):
                a = amount // INTERVALS[i]
                if a > 0: 
                    result.append( (a, NAMES[i][1 % a]) )
                    amount -= a * INTERVALS[i]
    
            return result
    
        rd = process_time(int(amount), units)
        cont = 0
        for u in rd:
            if u[0] > 0:
                cont += 1
    
        buf = ''
        i = 0
        for u in rd:
            if u[0] > 0:
                buf += "%d %s" % (u[0], u[1])
                cont -= 1
    
            if i < (len(rd)-1):
                if cont > 1:
                    buf += ", "
                else:
                    buf += " and "
    
            i += 1
    
        return buf
    

    Example of use:

    >>> print humanize_time(234567890 - 123456789)
    3 years, 9 months, 3 weeks, 5 days, 11 minutes and 41 seconds
    >>> humanize_time(9, 'weeks')
    2 months and 1 week
    

    Advantage (You don't need third parties!).

    Improved from "Liudmil Mitev" algorithm. (Thanks!)

    0 讨论(0)
  • 2020-12-23 20:08

    Check out the humanize package

    https://github.com/jmoiron/humanize

    import datetime
    
    humanize.naturaltime(datetime.datetime.now() - datetime.timedelta(seconds=1))
    
    'a second ago'
    
    humanize.naturaltime(datetime.datetime.now() - datetime.timedelta(seconds=3600))
    
    'an hour ago'
    
    0 讨论(0)
  • 2020-12-23 20:11

    You can use the wonderful dateutil module and its relativedelta class:

    import datetime
    import dateutil.relativedelta
    
    dt1 = datetime.datetime.fromtimestamp(123456789) # 1973-11-29 22:33:09
    dt2 = datetime.datetime.fromtimestamp(234567890) # 1977-06-07 23:44:50
    rd = dateutil.relativedelta.relativedelta (dt2, dt1)
    
    print "%d years, %d months, %d days, %d hours, %d minutes and %d seconds" % (rd.years, rd.months, rd.days, rd.hours, rd.minutes, rd.seconds)
    # 3 years, 6 months, 9 days, 1 hours, 11 minutes and 41 seconds
    

    It doesn't count weeks, but that shouldn't be too hard to add.

    0 讨论(0)
提交回复
热议问题