Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove when from naturaldelta() and allow largest timedelta #250

Merged
merged 4 commits into from
Feb 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 19 additions & 20 deletions src/humanize/time.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,24 +123,26 @@ def naturaldelta(
value,
months=True,
minimum_unit="seconds",
when=None,
) -> str:
"""Return a natural representation of a timedelta or number of seconds.

This is similar to `naturaltime`, but does not add tense to the result.

Args:
value (datetime.timedelta): A timedelta or a number of seconds.
value (datetime.timedelta or int): A timedelta or a number of seconds.
months (bool): If `True`, then a number of months (based on 30.5 days) will be
used for fuzziness between years.
minimum_unit (str): The lowest unit that can be used.
when (datetime.datetime): Point in time relative to which _value_ is
interpreted. Defaults to the current time in the local timezone.
Deprecated in version 3.14; If you need to construct a timedelta,
do it inline as the first argument.
when (datetime.datetime): Removed in version 4.0; If you need to
construct a timedelta, do it inline as the first argument.

Returns:
str: A natural representation of the amount of time elapsed.
str (str or `value`): A natural representation of the amount of time
elapsed unless `value` is not datetime.timedelta or cannot be
converted to int. In that case, a `value` is returned unchanged.

Raises:
OverflowError: If `value` is too large to convert to datetime.timedelta.

Examples
Compare two timestamps in a custom local timezone::
Expand All @@ -152,24 +154,21 @@ def naturaldelta(
now = dt.datetime.now(tz=berlin)
later = now + dt.timedelta(minutes=30)

assert naturaldelta(later, when=now) == "30 minutes"
assert naturaldelta(later - now) == "30 minutes"
"""
if when:
warnings.warn(
"The `when` parameter of `naturaldelta()` is deprecated and will be "
"removed in humanize 4.0. If you need to construct a timedelta, "
"do it inline as the first argument.",
DeprecationWarning,
stacklevel=2,
)
tmp = Unit[minimum_unit.upper()]
if tmp not in (Unit.SECONDS, Unit.MILLISECONDS, Unit.MICROSECONDS):
raise ValueError(f"Minimum unit '{minimum_unit}' not supported")
minimum_unit = tmp

date, delta = _date_and_delta(value, now=when)
if date is None:
return value
if isinstance(value, dt.timedelta):
delta = value
else:
try:
value = int(value)
delta = dt.timedelta(seconds=value)
except (ValueError, TypeError):
return value

use_months = months

Expand Down Expand Up @@ -274,7 +273,7 @@ def naturaltime(
future = date > now

ago = _("%s from now") if future else _("%s ago")
delta = naturaldelta(delta, months, minimum_unit, when=when)
delta = naturaldelta(delta, months, minimum_unit)

if delta == _("a moment"):
return _("now")
Expand Down
35 changes: 3 additions & 32 deletions tests/test_time.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,9 @@ def test_naturaldelta_nomonths(test_input, expected):
(dt.timedelta(days=9), "9 days"),
(dt.timedelta(days=365), "a year"),
(dt.timedelta(days=365 * 1_141), "1,141 years"),
("NaN", "NaN"),
("NaN", "NaN"), # Returns non-numbers unchanged.
# largest possible timedelta
(dt.timedelta(days=999_999_999), "2,739,726 years"),
],
)
def test_naturaldelta(test_input, expected):
Expand Down Expand Up @@ -333,37 +335,6 @@ def test_naturaldelta_minimum_unit_explicit(minimum_unit, seconds, expected):
assert humanize.naturaldelta(delta, minimum_unit=minimum_unit) == expected


@pytest.mark.parametrize(
"test_input, when, expected",
[
(NOW, NOW, "a moment"),
(NOW_UTC, NOW_UTC, "a moment"),
],
)
def test_naturaldelta_when_explicit(test_input, when, expected):
# Act / Assert
assert humanize.naturaldelta(test_input, when=when) == expected


@pytest.mark.parametrize(
"value, when",
[
(NOW_UTC, None),
(NOW_UTC, NOW),
(NOW_UTC_PLUS_01_00, None),
(NOW_UTC_PLUS_01_00, NOW),
],
)
def test_naturaldelta_when_missing_tzinfo(value, when):
"""Subtraction `when - value` is not defined by the `datetime` module when
either operand has not timezone-info (`tz=None`) and raises a TypeError.
"""

# Act / Assert
with pytest.raises(TypeError):
humanize.naturaldelta(value, when=when)


@pytest.mark.parametrize(
"seconds, expected",
[
Expand Down