Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # from github/Rapptz
- import datetime
- from dateutil.relativedelta import relativedelta
- class Plural:
- def __init__(self, value):
- self.value = value
- def __format__(self, format_spec):
- v = self.value
- singular, sep, plural = format_spec.partition('|')
- plural = plural or f'{singular}s'
- if abs(v) != 1:
- return f'{v} {plural}'
- return f'{v} {singular}'
- def human_join(seq, delim=', ', final='or'):
- size = len(seq)
- if size == 0:
- return ''
- if size == 1:
- return seq[0]
- if size == 2:
- return f'{seq[0]} {final} {seq[1]}'
- return delim.join(seq[:-1]) + f' {final} {seq[-1]}'
- def human_timedelta(dt, *, source=None, accuracy=3, brief=False, suffix=True):
- now = source or datetime.datetime.utcnow()
- # Microsecond free zone
- now = now.replace(microsecond=0)
- dt = dt.replace(microsecond=0)
- # This implementation uses relativedelta instead of the much more obvious
- # divmod approach with seconds because the seconds approach is not entirely
- # accurate once you go over 1 week in terms of accuracy since you have to
- # hardcode a month as 30 or 31 days.
- # A query like "11 months" can be interpreted as "!1 months and 6 days"
- if dt > now:
- delta = relativedelta(dt, now)
- suffix = ''
- else:
- delta = relativedelta(now, dt)
- suffix = ' ago' if suffix else ''
- attrs = [
- ('year', 'y'),
- ('month', 'mo'),
- ('day', 'd'),
- ('hour', 'h'),
- ('minute', 'm'),
- ('second', 's'),
- ]
- output = []
- for attr, brief_attr in attrs:
- elem = getattr(delta, attr + 's')
- if not elem:
- continue
- if attr == 'day':
- weeks = delta.weeks
- if weeks:
- elem -= weeks * 7
- if not brief:
- output.append(format(Plural(weeks), 'week'))
- else:
- output.append(f'{weeks}w')
- if elem <= 0:
- continue
- if brief:
- output.append(f'{elem}{brief_attr}')
- else:
- output.append(format(Plural(elem), attr))
- if accuracy is not None:
- output = output[:accuracy]
- if len(output) == 0:
- return 'now'
- else:
- if not brief:
- return human_join(output, final='and') + suffix
- else:
- return ' '.join(output) + suffix
Advertisement
Add Comment
Please, Sign In to add comment