Skip to content

Commit

Permalink
Dehumanize Support for Slavic Locales (#1077)
Browse files Browse the repository at this point in the history
  • Loading branch information
anishnya committed Dec 18, 2021
1 parent be57df5 commit a2ebb7e
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 2 deletions.
2 changes: 1 addition & 1 deletion arrow/arrow.py
Original file line number Diff line number Diff line change
Expand Up @@ -1384,7 +1384,7 @@ def dehumanize(self, input_string: str, locale: str = "en_us") -> "Arrow":
search_string = search_string.format(r"\d+")

# Create search pattern and find within string
pattern = re.compile(fr"{search_string}")
pattern = re.compile(fr"(^|\b|\d){search_string}")
match = pattern.search(input_string)

# If there is no match continue to next iteration
Expand Down
13 changes: 13 additions & 0 deletions arrow/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,20 @@
"zh-hk",
"nl",
"nl-nl",
"be",
"be-by",
"pl",
"pl-pl",
"ru",
"ru-ru",
"af",
"bg",
"bg-bg",
"ua",
"uk",
"uk-ua",
"mk",
"mk-mk",
"de",
"de-de",
"de-ch",
Expand Down
11 changes: 10 additions & 1 deletion arrow/locales.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,16 @@ def describe_multi(
humanized = " ".join(parts)

if not only_distance:
humanized = self._format_relative(humanized, *timeframes[-1])
# Needed to determine the correct relative string to use
timeframe_value = 0

for _unit_name, unit_value in timeframes:
if trunc(unit_value) != 0:
timeframe_value = trunc(unit_value)
break

# Note it doesn't matter the timeframe unit we use on the call, only the value
humanized = self._format_relative(humanized, "seconds", timeframe_value)

return humanized

Expand Down
71 changes: 71 additions & 0 deletions tests/test_arrow.py
Original file line number Diff line number Diff line change
Expand Up @@ -2373,7 +2373,20 @@ def locale_list_no_weeks() -> List[str]:
"zh-hk",
"nl",
"nl-nl",
"be",
"be-by",
"pl",
"pl-pl",
"ru",
"ru-ru",
"af",
"bg",
"bg-bg",
"ua",
"uk",
"uk-ua",
"mk",
"mk-mk",
"de",
"de-de",
"de-ch",
Expand Down Expand Up @@ -2485,6 +2498,12 @@ def locale_list_with_weeks() -> List[str]:
"zh-hk",
"nl",
"nl-nl",
"pl",
"pl-pl",
"ru",
"ru-ru",
"mk",
"mk-mk",
"de",
"de-de",
"de-ch",
Expand Down Expand Up @@ -2520,6 +2539,27 @@ def locale_list_with_weeks() -> List[str]:
return tested_langs


@pytest.fixture(scope="class")
def slavic_locales() -> List[str]:
tested_langs = [
"be",
"be-by",
"pl",
"pl-pl",
"ru",
"ru-ru",
"bg",
"bg-bg",
"ua",
"uk",
"uk-ua",
"mk",
"mk-mk",
]

return tested_langs


class TestArrowDehumanize:
def test_now(self, locale_list_no_weeks: List[str]):

Expand Down Expand Up @@ -2883,6 +2923,37 @@ def test_no_units_modified(self, locale_list_no_weeks: List[str]):
with pytest.raises(ValueError):
arw.dehumanize(empty_future_string, locale=lang)

def test_slavic_locales(self, slavic_locales: List[str]):

# Relevant units for Slavic locale plural logic
units = [
0,
1,
2,
5,
21,
22,
25,
]

# Only need to test on seconds as logic holds for all slavic plural units
for lang in slavic_locales:
for unit in units:
arw = arrow.Arrow(2000, 2, 18, 1, 50, 30)

past = arw.shift(minutes=-1 * unit, days=-1)
future = arw.shift(minutes=unit, days=1)

past_string = past.humanize(
arw, locale=lang, granularity=["minute", "day"]
)
future_string = future.humanize(
arw, locale=lang, granularity=["minute", "day"]
)

assert arw.dehumanize(past_string, locale=lang) == past
assert arw.dehumanize(future_string, locale=lang) == future


class TestArrowIsBetween:
def test_start_before_end(self):
Expand Down

0 comments on commit a2ebb7e

Please sign in to comment.