Skip to content

Commit a2ebb7e

Browse files
authored
Dehumanize Support for Slavic Locales (#1077)
1 parent be57df5 commit a2ebb7e

File tree

4 files changed

+95
-2
lines changed

4 files changed

+95
-2
lines changed

arrow/arrow.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1384,7 +1384,7 @@ def dehumanize(self, input_string: str, locale: str = "en_us") -> "Arrow":
13841384
search_string = search_string.format(r"\d+")
13851385

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

13901390
# If there is no match continue to next iteration

arrow/constants.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,20 @@
7373
"zh-hk",
7474
"nl",
7575
"nl-nl",
76+
"be",
77+
"be-by",
78+
"pl",
79+
"pl-pl",
80+
"ru",
81+
"ru-ru",
7682
"af",
83+
"bg",
84+
"bg-bg",
85+
"ua",
86+
"uk",
87+
"uk-ua",
88+
"mk",
89+
"mk-mk",
7790
"de",
7891
"de-de",
7992
"de-ch",

arrow/locales.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,16 @@ def describe_multi(
172172
humanized = " ".join(parts)
173173

174174
if not only_distance:
175-
humanized = self._format_relative(humanized, *timeframes[-1])
175+
# Needed to determine the correct relative string to use
176+
timeframe_value = 0
177+
178+
for _unit_name, unit_value in timeframes:
179+
if trunc(unit_value) != 0:
180+
timeframe_value = trunc(unit_value)
181+
break
182+
183+
# Note it doesn't matter the timeframe unit we use on the call, only the value
184+
humanized = self._format_relative(humanized, "seconds", timeframe_value)
176185

177186
return humanized
178187

tests/test_arrow.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2373,7 +2373,20 @@ def locale_list_no_weeks() -> List[str]:
23732373
"zh-hk",
23742374
"nl",
23752375
"nl-nl",
2376+
"be",
2377+
"be-by",
2378+
"pl",
2379+
"pl-pl",
2380+
"ru",
2381+
"ru-ru",
23762382
"af",
2383+
"bg",
2384+
"bg-bg",
2385+
"ua",
2386+
"uk",
2387+
"uk-ua",
2388+
"mk",
2389+
"mk-mk",
23772390
"de",
23782391
"de-de",
23792392
"de-ch",
@@ -2485,6 +2498,12 @@ def locale_list_with_weeks() -> List[str]:
24852498
"zh-hk",
24862499
"nl",
24872500
"nl-nl",
2501+
"pl",
2502+
"pl-pl",
2503+
"ru",
2504+
"ru-ru",
2505+
"mk",
2506+
"mk-mk",
24882507
"de",
24892508
"de-de",
24902509
"de-ch",
@@ -2520,6 +2539,27 @@ def locale_list_with_weeks() -> List[str]:
25202539
return tested_langs
25212540

25222541

2542+
@pytest.fixture(scope="class")
2543+
def slavic_locales() -> List[str]:
2544+
tested_langs = [
2545+
"be",
2546+
"be-by",
2547+
"pl",
2548+
"pl-pl",
2549+
"ru",
2550+
"ru-ru",
2551+
"bg",
2552+
"bg-bg",
2553+
"ua",
2554+
"uk",
2555+
"uk-ua",
2556+
"mk",
2557+
"mk-mk",
2558+
]
2559+
2560+
return tested_langs
2561+
2562+
25232563
class TestArrowDehumanize:
25242564
def test_now(self, locale_list_no_weeks: List[str]):
25252565

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

2926+
def test_slavic_locales(self, slavic_locales: List[str]):
2927+
2928+
# Relevant units for Slavic locale plural logic
2929+
units = [
2930+
0,
2931+
1,
2932+
2,
2933+
5,
2934+
21,
2935+
22,
2936+
25,
2937+
]
2938+
2939+
# Only need to test on seconds as logic holds for all slavic plural units
2940+
for lang in slavic_locales:
2941+
for unit in units:
2942+
arw = arrow.Arrow(2000, 2, 18, 1, 50, 30)
2943+
2944+
past = arw.shift(minutes=-1 * unit, days=-1)
2945+
future = arw.shift(minutes=unit, days=1)
2946+
2947+
past_string = past.humanize(
2948+
arw, locale=lang, granularity=["minute", "day"]
2949+
)
2950+
future_string = future.humanize(
2951+
arw, locale=lang, granularity=["minute", "day"]
2952+
)
2953+
2954+
assert arw.dehumanize(past_string, locale=lang) == past
2955+
assert arw.dehumanize(future_string, locale=lang) == future
2956+
28862957

28872958
class TestArrowIsBetween:
28882959
def test_start_before_end(self):

0 commit comments

Comments
 (0)