diff --git a/src/humanize/time.py b/src/humanize/time.py index 4a07d52..4b8bd9c 100644 --- a/src/humanize/time.py +++ b/src/humanize/time.py @@ -245,6 +245,17 @@ def naturaldelta( return _ngettext("1 year, %d day", "1 year, %d days", days) % days + if use_months and 0 < num_months < 12: + years_str = _ngettext("%d year", "%d years", years).replace( + "%d", "%s" + ) % intcomma(years) + months_str = _ngettext("%d month", "%d months", num_months) % num_months + return f"{years_str}, {months_str}" + if use_months and num_months == 12: + years += 1 + return _ngettext("%d year", "%d years", years).replace("%d", "%s") % intcomma( + years + ) return _ngettext("%d year", "%d years", years).replace("%d", "%s") % intcomma(years) diff --git a/tests/test_time.py b/tests/test_time.py index 7699770..f5a1695 100644 --- a/tests/test_time.py +++ b/tests/test_time.py @@ -112,15 +112,15 @@ def test_naturaldelta_nomonths(test_input: dt.timedelta, expected: str) -> None: (dt.timedelta(hours=23, minutes=50, seconds=50), "a day"), (dt.timedelta(days=1), "a day"), (dt.timedelta(days=500), "1 year, 4 months"), - (dt.timedelta(days=365 * 2 + 35), "2 years"), + (dt.timedelta(days=365 * 2 + 35), "2 years, 1 month"), (dt.timedelta(seconds=1), "a second"), (dt.timedelta(seconds=30), "30 seconds"), (dt.timedelta(days=364), "a year"), (dt.timedelta(days=365 + 364), "2 years"), # regression tests for bugs in post-release humanize - (dt.timedelta(days=10000), "27 years"), + (dt.timedelta(days=10000), "27 years, 5 months"), (dt.timedelta(days=365 + 35), "1 year, 1 month"), - (dt.timedelta(days=365 * 2 + 65), "2 years"), + (dt.timedelta(days=365 * 2 + 65), "2 years, 2 months"), (dt.timedelta(days=365 + 4), "1 year, 4 days"), (dt.timedelta(days=35), "a month"), (dt.timedelta(days=65), "2 months"), @@ -154,7 +154,7 @@ def test_naturaldelta(test_input: float | dt.timedelta, expected: str) -> None: (NOW - dt.timedelta(hours=23, minutes=50, seconds=50), "a day ago"), (NOW - dt.timedelta(days=1), "a day ago"), (NOW - dt.timedelta(days=500), "1 year, 4 months ago"), - (NOW - dt.timedelta(days=365 * 2 + 35), "2 years ago"), + (NOW - dt.timedelta(days=365 * 2 + 35), "2 years, 1 month ago"), (NOW + dt.timedelta(seconds=1), "a second from now"), (NOW + dt.timedelta(seconds=30), "30 seconds from now"), (NOW + dt.timedelta(minutes=1, seconds=29), "a minute from now"), @@ -166,17 +166,17 @@ def test_naturaldelta(test_input: float | dt.timedelta, expected: str) -> None: (NOW + dt.timedelta(hours=23, minutes=50, seconds=50), "a day from now"), (NOW + dt.timedelta(days=1), "a day from now"), (NOW + dt.timedelta(days=500), "1 year, 4 months from now"), - (NOW + dt.timedelta(days=365 * 2 + 35), "2 years from now"), + (NOW + dt.timedelta(days=365 * 2 + 35), "2 years, 1 month from now"), # regression tests for bugs in post-release humanize - (NOW + dt.timedelta(days=10000), "27 years from now"), + (NOW + dt.timedelta(days=10000), "27 years, 5 months from now"), (NOW - dt.timedelta(days=365 + 35), "1 year, 1 month ago"), - (dt.timedelta(days=-10000), "27 years from now"), + (dt.timedelta(days=-10000), "27 years, 5 months from now"), (dt.timedelta(days=365 + 35), "1 year, 1 month ago"), (22.5, "22 seconds ago"), (23.5, "24 seconds ago"), (23.9, "24 seconds ago"), (30, "30 seconds ago"), - (NOW - dt.timedelta(days=365 * 2 + 65), "2 years ago"), + (NOW - dt.timedelta(days=365 * 2 + 65), "2 years, 2 months ago"), (NOW - dt.timedelta(days=365 + 4), "1 year, 4 days ago"), ("NaN", "NaN"), ], @@ -479,7 +479,7 @@ def test_naturaltime_minimum_unit_explicit( (NOW_UTC - dt.timedelta(hours=23, minutes=50, seconds=50), "a day ago"), (NOW_UTC - dt.timedelta(days=1), "a day ago"), (NOW_UTC - dt.timedelta(days=500), "1 year, 4 months ago"), - (NOW_UTC - dt.timedelta(days=365 * 2 + 35), "2 years ago"), + (NOW_UTC - dt.timedelta(days=365 * 2 + 35), "2 years, 1 month ago"), (NOW_UTC + dt.timedelta(seconds=1), "a second from now"), (NOW_UTC + dt.timedelta(seconds=30), "30 seconds from now"), (NOW_UTC + dt.timedelta(minutes=1, seconds=29), "a minute from now"), @@ -491,11 +491,11 @@ def test_naturaltime_minimum_unit_explicit( (NOW_UTC + dt.timedelta(hours=23, minutes=50, seconds=50), "a day from now"), (NOW_UTC + dt.timedelta(days=1), "a day from now"), (NOW_UTC + dt.timedelta(days=500), "1 year, 4 months from now"), - (NOW_UTC + dt.timedelta(days=365 * 2 + 35), "2 years from now"), + (NOW_UTC + dt.timedelta(days=365 * 2 + 35), "2 years, 1 month from now"), # regression tests for bugs in post-release humanize - (NOW_UTC + dt.timedelta(days=10000), "27 years from now"), + (NOW_UTC + dt.timedelta(days=10000), "27 years, 5 months from now"), (NOW_UTC - dt.timedelta(days=365 + 35), "1 year, 1 month ago"), - (NOW_UTC - dt.timedelta(days=365 * 2 + 65), "2 years ago"), + (NOW_UTC - dt.timedelta(days=365 * 2 + 65), "2 years, 2 months ago"), (NOW_UTC - dt.timedelta(days=365 + 4), "1 year, 4 days ago"), ], ) @@ -519,7 +519,7 @@ def test_naturaltime_timezone(test_input: dt.datetime, expected: str) -> None: (NOW_UTC - dt.timedelta(hours=23, minutes=50, seconds=50), "a day ago"), (NOW_UTC - dt.timedelta(days=1), "a day ago"), (NOW_UTC - dt.timedelta(days=500), "1 year, 4 months ago"), - (NOW_UTC - dt.timedelta(days=365 * 2 + 35), "2 years ago"), + (NOW_UTC - dt.timedelta(days=365 * 2 + 35), "2 years, 1 month ago"), (NOW_UTC + dt.timedelta(seconds=1), "a second from now"), (NOW_UTC + dt.timedelta(seconds=30), "30 seconds from now"), (NOW_UTC + dt.timedelta(minutes=1, seconds=29), "a minute from now"), @@ -531,11 +531,11 @@ def test_naturaltime_timezone(test_input: dt.datetime, expected: str) -> None: (NOW_UTC + dt.timedelta(hours=23, minutes=50, seconds=50), "a day from now"), (NOW_UTC + dt.timedelta(days=1), "a day from now"), (NOW_UTC + dt.timedelta(days=500), "1 year, 4 months from now"), - (NOW_UTC + dt.timedelta(days=365 * 2 + 35), "2 years from now"), + (NOW_UTC + dt.timedelta(days=365 * 2 + 35), "2 years, 1 month from now"), # regression tests for bugs in post-release humanize - (NOW_UTC + dt.timedelta(days=10000), "27 years from now"), + (NOW_UTC + dt.timedelta(days=10000), "27 years, 5 months from now"), (NOW_UTC - dt.timedelta(days=365 + 35), "1 year, 1 month ago"), - (NOW_UTC - dt.timedelta(days=365 * 2 + 65), "2 years ago"), + (NOW_UTC - dt.timedelta(days=365 * 2 + 65), "2 years, 2 months ago"), (NOW_UTC - dt.timedelta(days=365 + 4), "1 year, 4 days ago"), ], )