From c74d5498f869919a30eb3484c9dbc2bc2ef26d63 Mon Sep 17 00:00:00 2001 From: agbesiprincekwabena-cmd Date: Thu, 24 Sep 2026 15:30:15 +0000 Subject: [PATCH 1/2] Fix precisedelta to handle negative timedelta --- src/humanize/time.py | 87 +++++++++----------------------------------- 1 file changed, 17 insertions(+), 70 deletions(-) diff --git a/src/humanize/time.py b/src/humanize/time.py index 82a80424..36100bbd 100644 --- a/src/humanize/time.py +++ b/src/humanize/time.py @@ -482,72 +482,16 @@ def precisedelta( suppress: Iterable[str] = (), format: str = "%0.2f", ) -> str: - """Return a precise representation of a timedelta or number of seconds. - - ```pycon - >>> import datetime as dt - >>> from humanize.time import precisedelta - - >>> delta = dt.timedelta(seconds=3633, days=2, microseconds=123000) - >>> precisedelta(delta) - '2 days, 1 hour and 33.12 seconds' - - ``` - - A custom `format` can be specified to control how the fractional part - is represented: - - ```pycon - >>> precisedelta(delta, format="%0.4f") - '2 days, 1 hour and 33.1230 seconds' - - ``` - - Instead, the `minimum_unit` can be changed to have a better resolution; - the function will still readjust the unit to use the greatest of the - units that does not lose precision. - - For example setting microseconds but still representing the date with milliseconds: - - ```pycon - >>> precisedelta(delta, minimum_unit="microseconds") - '2 days, 1 hour, 33 seconds and 123 milliseconds' - - ``` - - If desired, some units can be suppressed: you will not see them represented and the - time of the other units will be adjusted to keep representing the same timedelta: - - ```pycon - >>> precisedelta(delta, suppress=['days']) - '49 hours and 33.12 seconds' - - ``` - - Note that microseconds precision is lost if the seconds and all - the units below are suppressed: - - ```pycon - >>> delta = dt.timedelta(seconds=90, microseconds=100) - >>> precisedelta(delta, suppress=['seconds', 'milliseconds', 'microseconds']) - '1.50 minutes' - - ``` - - If the delta is too small to be represented with the minimum unit, - a value of zero will be returned: - - ```pycon - >>> delta = dt.timedelta(seconds=1) - >>> precisedelta(delta, minimum_unit="minutes") - '0.02 minutes' - - >>> delta = dt.timedelta(seconds=0.1) - >>> precisedelta(delta, minimum_unit="minutes") - '0 minutes' + import datetime as dt + is_negative = False + if isinstance(value, dt.timedelta): + if value.total_seconds() < 0: + is_negative = True + value = abs(value) + elif isinstance(value, (int, float)) and value < 0: + is_negative = True + value = abs(value) - ``` - """ date, delta = _date_and_delta(value, precise=True) if date is None: return str(value) @@ -675,12 +619,15 @@ def precisedelta( break if len(texts) == 1: - return texts[0] - - head = ", ".join(texts[:-1]) - tail = texts[-1] + result = texts[0] + else: + head = ", ".join(texts[:-1]) + tail = texts[-1] + result = _("%s and %s") % (head, tail) - return _("%s and %s") % (head, tail) + if is_negative: + return f"-{result}" + return result def _rounding_by_fmt(format: str, value: float) -> float | int: From 0016dfe44bd6e3abaf57d58221b783b31556f46f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 24 Sep 2026 15:37:01 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/humanize/time.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/humanize/time.py b/src/humanize/time.py index 36100bbd..0d075d77 100644 --- a/src/humanize/time.py +++ b/src/humanize/time.py @@ -483,6 +483,7 @@ def precisedelta( format: str = "%0.2f", ) -> str: import datetime as dt + is_negative = False if isinstance(value, dt.timedelta): if value.total_seconds() < 0: