inflect icon indicating copy to clipboard operation
inflect copied to clipboard

time difference inflected as before/after

Open jaraco opened this issue 8 years ago • 1 comments

I'd like to see a feature like the following:

>>> p.date_diff(datetime.timedelta(minutes=-30))
'00:30:00 before'
>>> p.date_diff(5)
'00:00:05 after'
>>> p.date_diff(0)
'at'

I would expect one to use the result to produce nice output for a time difference like:

Your flight departed 00:00:05 after its scheduled departure.

It would be nice if it accepted a time formatter such that it could alternately emit:

>>> p.date_diff(datetime.timedelta(minutes=-30), fmt=nice_time)
'30 minutes before'
>>> p.date_diff(5, fmt=nice_time)
'five seconds after'
>>> p.date_diff(0, fmt=nice_time)
'at'

Perhaps that inflection is too trivial for a library like inflect. Or perhaps there are nuances I haven't yet considered.

jaraco avatar Mar 30 '17 18:03 jaraco

The timeago package will format a datetime object as a "X time ago" statement.

It might also be useful to be able to convert a timedelta, or time in seconds, to a natural language time string.

Cribbing StackOverflow, here's a simple converter from seconds to a natural time, but it might make more sense to base something around a timedelta object?

#https://stackoverflow.com/a/24542445/454773
intervals = (
    ('weeks', 604800),  # 60 * 60 * 24 * 7
    ('days', 86400),    # 60 * 60 * 24
    ('hours', 3600),    # 60 * 60
    ('minutes', 60),
    ('seconds', 1),
    )
    
def display_time(seconds, granularity=3, sep=',', andword='and'):
    """Take a time in seconds and return a sensible
        natural language interpretation of it."""
    def nl_join(l):
        if len(l)>2:
            return ', '.join(f'{l[:-1]} {andword} {str(l[-1])}')
        elif len(l)==2:
            return f' {andword} '.join(l)
        return l[0]
    
    result = []

    for name, count in intervals:
        value = seconds // count
        if value:
            seconds -= value * count
            if value == 1:
                name = name.rstrip('s')
            result.append("{} {}".format(value, name))

    return nl_join(result[:granularity])

psychemedia avatar Jan 07 '20 16:01 psychemedia