Skip to content

Commit 89f77b1

Browse files
committed
Add an "all" granularity to humanize
It's more convenient to pass a simple short string than to pass a list of 7 strings. Resolve arrow-py#1014
1 parent 2ade710 commit 89f77b1

File tree

3 files changed

+53
-2
lines changed

3 files changed

+53
-2
lines changed

arrow/arrow.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969

7070
_GRANULARITY = Literal[
7171
"auto",
72+
"all",
7273
"second",
7374
"minute",
7475
"hour",
@@ -1130,7 +1131,8 @@ def humanize(
11301131
:param locale: (optional) a ``str`` specifying a locale. Defaults to 'en-us'.
11311132
:param only_distance: (optional) returns only time difference eg: "11 seconds" without "in" or "ago" part.
11321133
:param granularity: (optional) defines the precision of the output. Set it to strings 'second', 'minute',
1133-
'hour', 'day', 'week', 'month' or 'year' or a list of any combination of these strings
1134+
'hour', 'day', 'week', 'month' or 'year' or a list of any combination of these strings.
1135+
Set it to 'all' to include all possible units in the granularity.
11341136
11351137
Usage::
11361138
@@ -1228,7 +1230,7 @@ def humanize(
12281230
years = sign * max(delta_second // self._SECS_PER_YEAR, 2)
12291231
return locale.describe("years", years, only_distance=only_distance)
12301232

1231-
elif isinstance(granularity, str):
1233+
elif isinstance(granularity, str) and granularity != "all":
12321234
granularity = cast(TimeFrameLiteral, granularity) # type: ignore[assignment]
12331235

12341236
if granularity == "second":
@@ -1282,6 +1284,10 @@ def gather_timeframes(_delta: float, _frame: TimeFrameLiteral) -> float:
12821284
"minute",
12831285
"second",
12841286
)
1287+
1288+
if granularity == "all":
1289+
granularity = cast(List[_GRANULARITY], frames)
1290+
12851291
for frame in frames:
12861292
delta = gather_timeframes(delta, frame)
12871293

docs/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,8 @@ Indicate a specific time granularity (or multiple):
242242
'an hour and 6 minutes ago'
243243
>>> future.humanize(present, only_distance=True, granularity=["hour", "minute"])
244244
'an hour and 6 minutes'
245+
>>> future.humanize(present, granularity="all")
246+
'in 0 years 0 months 0 weeks 0 days an hour 6 minutes and 0 seconds'
245247
246248
Support for a growing number of locales (see ``locales.py`` for supported languages):
247249

tests/test_arrow.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2032,6 +2032,49 @@ def test_multiple_granularity(self):
20322032
== "a minute and 2 seconds ago"
20332033
)
20342034

2035+
def test_all_granularity(self):
2036+
assert (
2037+
self.now.humanize(granularity="all")
2038+
== "in 0 years 0 months 0 weeks 0 days 0 hours 0 minutes and 0 seconds"
2039+
) # TODO: this should be "ago"; change this when #997 is merged
2040+
2041+
later105 = self.now.shift(seconds=10 ** 5)
2042+
assert (
2043+
self.now.humanize(later105, granularity="all")
2044+
== "0 years 0 months 0 weeks a day 3 hours 46 minutes and 40 seconds ago"
2045+
)
2046+
assert (
2047+
later105.humanize(self.now, granularity="all")
2048+
== "in 0 years 0 months 0 weeks a day 3 hours 46 minutes and 40 seconds"
2049+
)
2050+
2051+
later108 = self.now.shift(seconds=10 ** 8)
2052+
assert (
2053+
self.now.humanize(later108, granularity="all")
2054+
== "3 years 2 months 0 weeks a day 9 hours 46 minutes and 40 seconds ago"
2055+
)
2056+
assert (
2057+
later108.humanize(self.now, granularity="all")
2058+
== "in 3 years 2 months 0 weeks a day 9 hours 46 minutes and 40 seconds"
2059+
)
2060+
assert (
2061+
self.now.humanize(later108, granularity="all", only_distance=True)
2062+
== "3 years 2 months 0 weeks a day 9 hours 46 minutes and 40 seconds"
2063+
)
2064+
2065+
later_two_months = self.now.shift(months=2)
2066+
assert (
2067+
self.now.humanize(later_two_months, granularity="all")
2068+
== "in 0 years 2 months 0 weeks 0 days 0 hours 0 minutes and 0 seconds"
2069+
) # TODO: this should be "ago"; change this when #997 is merged
2070+
assert (
2071+
later_two_months.humanize(self.now, granularity="all")
2072+
== "in 0 years 2 months 0 weeks 0 days 0 hours 0 minutes and 0 seconds"
2073+
)
2074+
2075+
with pytest.raises(ValueError):
2076+
self.now.humanize(later108, granularity=["all", "year"])
2077+
20352078
def test_seconds(self):
20362079

20372080
later = self.now.shift(seconds=10)

0 commit comments

Comments
 (0)