From b72a39ee66f1189efda3814e3b1dd98d68fa1e48 Mon Sep 17 00:00:00 2001 From: Hartmut Obendorf Date: Wed, 21 Feb 2024 16:59:17 +0100 Subject: [PATCH 1/2] Added parameter for format_timedelta to return several units on demand (depth=full for all non-zero units, depth=fullest for all) --- babel/dates.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/babel/dates.py b/babel/dates.py index 40d950983..b1c380ed8 100644 --- a/babel/dates.py +++ b/babel/dates.py @@ -19,6 +19,7 @@ import re import warnings +import math from functools import lru_cache from typing import TYPE_CHECKING, SupportsInt @@ -862,6 +863,7 @@ def format_timedelta( threshold: float = .85, add_direction: bool = False, format: Literal['narrow', 'short', 'medium', 'long'] = 'long', + depth: Literal['shallow', 'full', 'fullest'] = 'shallow', locale: Locale | str | None = LC_TIME, ) -> str: """Return a time delta according to the rules of the given locale. @@ -945,12 +947,16 @@ def _iter_patterns(a_unit): a_unit = f"duration-{a_unit}" yield locale._data['unit_patterns'].get(a_unit, {}).get(format) + formatted_string = '' for unit, secs_per_unit in TIMEDELTA_UNITS: value = abs(seconds) / secs_per_unit - if value >= threshold or unit == granularity: + if value >= threshold or unit == granularity or (formatted_string and depth == 'fullest'): if unit == granularity and value > 0: value = max(1, value) - value = int(round(value)) + if depth == 'shallow' or unit == granularity: + value = int(round(value)) + else: + value = int(math.floor(value)) plural_form = locale.plural_form(value) pattern = None for patterns in _iter_patterns(unit): @@ -960,9 +966,14 @@ def _iter_patterns(a_unit): # This really should not happen if pattern is None: return '' - return pattern.replace('{0}', str(value)) - - return '' + if (depth=='shallow'): + formatted_string = ' '.join([formatted_string, pattern.replace('{0}', str(value))]) + break + elif ((depth=='full' and value > 0) or depth == 'fullest'): + formatted_string = ' '.join([formatted_string, pattern.replace('{0}', str(value))]) + seconds = seconds - value * secs_per_unit + + return formatted_string def _format_fallback_interval( From 8683607778639ba22c6ac10bef2b41ab748c3fd8 Mon Sep 17 00:00:00 2001 From: Hartmut Obendorf Date: Wed, 21 Feb 2024 17:24:51 +0100 Subject: [PATCH 2/2] fixed leading whitespace in return string --- babel/dates.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/babel/dates.py b/babel/dates.py index b1c380ed8..7946765ec 100644 --- a/babel/dates.py +++ b/babel/dates.py @@ -967,10 +967,10 @@ def _iter_patterns(a_unit): if pattern is None: return '' if (depth=='shallow'): - formatted_string = ' '.join([formatted_string, pattern.replace('{0}', str(value))]) + formatted_string = ' '.join(filter(None, [formatted_string, pattern.replace('{0}', str(value))])) break elif ((depth=='full' and value > 0) or depth == 'fullest'): - formatted_string = ' '.join([formatted_string, pattern.replace('{0}', str(value))]) + formatted_string = ' '.join(filter(None, [formatted_string, pattern.replace('{0}', str(value))])) seconds = seconds - value * secs_per_unit return formatted_string