from datetime import timedelta import re def parse_timedelta(s: str) -> timedelta: """ Parses a timespan. Format examples: "30m" "10s" "90d" "1h30m" "73d18h22m52s" """ p = re.compile('^(?:[0-9]+[dhms])+$') if p.match(s) is None: raise ValueError("Illegal timespan value '{s}'.") p = re.compile('([0-9]+)([dhms])') days = 0 hours = 0 minutes = 0 seconds = 0 for m in p.finditer(s): scalar = int(m.group(1)) unit = m.group(2) if unit == 'd': days = scalar elif unit == 'h': hours = scalar elif unit == 'm': minutes = scalar elif unit == 's': seconds = scalar return timedelta(days=days, hours=hours, minutes=minutes, seconds=seconds) def describe_timedelta(td: timedelta, max_components: int = 2) -> str: values = [ td.days, td.seconds // 3600, (td.seconds // 60) % 60, td.seconds % 60, ] units = [ 'day' if values[0] == 1 else 'days', 'hour' if values[1] == 1 else 'hours', 'minute' if values[2] == 1 else 'minutes', 'second' if values[3] == 1 else 'seconds', ] while len(values) > 1 and values[0] == 0: values.pop(0) units.pop(0) if len(values) > max_components: values = values[0:max_components] units = units[0:max_components] while len(values) > 1 and values[-1] == 0: values.pop(-1) units.pop(-1) tokens = [] for i in range(len(values)): tokens.append(f'{values[i]} {units[i]}') return ' '.join(tokens)