From c9cae9e8c25f021bc1b0075ad7eba25d10463308 Mon Sep 17 00:00:00 2001 From: Ching-Yi <82449718+ChingYi-AX@users.noreply.github.com> Date: Fri, 18 Feb 2022 06:13:46 +0100 Subject: [PATCH] Add Amharic Locale (#1093) --- arrow/constants.py | 2 + arrow/locales.py | 171 ++++++++++++++++++++++++++++++++++++++++++ tests/test_locales.py | 76 +++++++++++++++++++ 3 files changed, 249 insertions(+) diff --git a/arrow/constants.py b/arrow/constants.py index 92665043..4c6fa5cb 100644 --- a/arrow/constants.py +++ b/arrow/constants.py @@ -166,4 +166,6 @@ "ka-ge", "kk", "kk-kz", + "am", + "am-et", } diff --git a/arrow/locales.py b/arrow/locales.py index 4164ebdf..d5652370 100644 --- a/arrow/locales.py +++ b/arrow/locales.py @@ -6100,3 +6100,174 @@ class KazakhLocale(Locale): "Жексенбі", ] day_abbreviations = ["", "Дс", "Сс", "Ср", "Бс", "Жм", "Сб", "Жс"] + + +class AmharicLocale(Locale): + names = ["am", "am-et"] + + past = "{0} በፊት" + future = "{0} ውስጥ" + and_word = "እና" + + timeframes: ClassVar[Mapping[TimeFrameLiteral, Union[Mapping[str, str], str]]] = { + "now": "አሁን", + "second": { + "past": "ከአንድ ሰከንድ", + "future": "በአንድ ሰከንድ", + }, + "seconds": { + "past": "ከ {0} ሰከንድ", + "future": "በ {0} ሰከንድ", + }, + "minute": { + "past": "ከአንድ ደቂቃ", + "future": "በአንድ ደቂቃ", + }, + "minutes": { + "past": "ከ {0} ደቂቃዎች", + "future": "በ {0} ደቂቃዎች", + }, + "hour": { + "past": "ከአንድ ሰዓት", + "future": "በአንድ ሰዓት", + }, + "hours": { + "past": "ከ {0} ሰዓታት", + "future": "በ {0} ሰከንድ", + }, + "day": { + "past": "ከአንድ ቀን", + "future": "በአንድ ቀን", + }, + "days": { + "past": "ከ {0} ቀናት", + "future": "በ {0} ቀናት", + }, + "week": { + "past": "ከአንድ ሳምንት", + "future": "በአንድ ሳምንት", + }, + "weeks": { + "past": "ከ {0} ሳምንታት", + "future": "በ {0} ሳምንታት", + }, + "month": { + "past": "ከአንድ ወር", + "future": "በአንድ ወር", + }, + "months": { + "past": "ከ {0} ወር", + "future": "በ {0} ወራት", + }, + "year": { + "past": "ከአንድ አመት", + "future": "በአንድ አመት", + }, + "years": { + "past": "ከ {0} ዓመታት", + "future": "በ {0} ዓመታት", + }, + } + # Amharic: the general format to describe timeframe is different from past and future, + # so we do not copy the original timeframes dictionary + timeframes_only_distance = { + "second": "አንድ ሰከንድ", + "seconds": "{0} ሰከንድ", + "minute": "አንድ ደቂቃ", + "minutes": "{0} ደቂቃዎች", + "hour": "አንድ ሰዓት", + "hours": "{0} ሰዓት", + "day": "አንድ ቀን", + "days": "{0} ቀናት", + "week": "አንድ ሳምንት", + "weeks": "{0} ሳምንት", + "month": "አንድ ወር", + "months": "{0} ወራት", + "year": "አንድ አመት", + "years": "{0} ዓመታት", + } + + month_names = [ + "", + "ጃንዩወሪ", + "ፌብሩወሪ", + "ማርች", + "ኤፕሪል", + "ሜይ", + "ጁን", + "ጁላይ", + "ኦገስት", + "ሴፕቴምበር", + "ኦክቶበር", + "ኖቬምበር", + "ዲሴምበር", + ] + + month_abbreviations = [ + "", + "ጃንዩ", + "ፌብሩ", + "ማርች", + "ኤፕሪ", + "ሜይ", + "ጁን", + "ጁላይ", + "ኦገስ", + "ሴፕቴ", + "ኦክቶ", + "ኖቬም", + "ዲሴም", + ] + + day_names = [ + "", + "ሰኞ", + "ማክሰኞ", + "ረቡዕ", + "ሐሙስ", + "ዓርብ", + "ቅዳሜ", + "እሑድ", + ] + day_abbreviations = ["", "እ", "ሰ", "ማ", "ረ", "ሐ", "ዓ", "ቅ"] + + def _ordinal_number(self, n: int) -> str: + return f"{n}ኛ" + + def _format_timeframe(self, timeframe: TimeFrameLiteral, delta: int) -> str: + """ + Amharic awares time frame format function, takes into account + the differences between general, past, and future forms (three different suffixes). + """ + abs_delta = abs(delta) + form = self.timeframes[timeframe] + + if isinstance(form, str): + return form.format(abs_delta) + + if delta > 0: + key = "future" + else: + key = "past" + form = form[key] + + return form.format(abs_delta) + + def describe( + self, + timeframe: TimeFrameLiteral, + delta: Union[float, int] = 1, # key is always future when only_distance=False + only_distance: bool = False, + ) -> str: + """Describes a delta within a timeframe in plain language. + + :param timeframe: a string representing a timeframe. + :param delta: a quantity representing a delta in a timeframe. + :param only_distance: return only distance eg: "11 seconds" without "in" or "ago" keywords + """ + + if not only_distance: + return super().describe(timeframe, delta, only_distance) + humanized = self.timeframes_only_distance[timeframe].format(trunc(abs(delta))) + + return humanized diff --git a/tests/test_locales.py b/tests/test_locales.py index ba2300bd..0e42074d 100644 --- a/tests/test_locales.py +++ b/tests/test_locales.py @@ -2919,3 +2919,79 @@ def test_weekday(self): dt = arrow.Arrow(2015, 4, 11, 17, 30, 00) assert self.locale.day_name(dt.isoweekday()) == "lørdag" assert self.locale.day_abbreviation(dt.isoweekday()) == "lør" + + +@pytest.mark.usefixtures("lang_locale") +class TestAmharicLocale: + def test_format_timeframe(self): + assert self.locale._format_timeframe("now", 0) == "አሁን" + # second(s) + assert self.locale._format_timeframe("second", 1) == "በአንድ ሰከንድ" + assert self.locale._format_timeframe("second", -1) == "ከአንድ ሰከንድ" + assert self.locale._format_timeframe("seconds", 6) == "በ 6 ሰከንድ" + assert self.locale._format_timeframe("seconds", -36) == "ከ 36 ሰከንድ" + # minute(s) + assert self.locale._format_timeframe("minute", 1) == "በአንድ ደቂቃ" + assert self.locale._format_timeframe("minute", -1) == "ከአንድ ደቂቃ" + assert self.locale._format_timeframe("minutes", 7) == "በ 7 ደቂቃዎች" + assert self.locale._format_timeframe("minutes", -20) == "ከ 20 ደቂቃዎች" + # hour(s) + assert self.locale._format_timeframe("hour", 1) == "በአንድ ሰዓት" + assert self.locale._format_timeframe("hour", -1) == "ከአንድ ሰዓት" + assert self.locale._format_timeframe("hours", 7) == "በ 7 ሰከንድ" + assert self.locale._format_timeframe("hours", -20) == "ከ 20 ሰዓታት" + # day(s) + assert self.locale._format_timeframe("day", 1) == "በአንድ ቀን" + assert self.locale._format_timeframe("day", -1) == "ከአንድ ቀን" + assert self.locale._format_timeframe("days", 7) == "በ 7 ቀናት" + assert self.locale._format_timeframe("days", -20) == "ከ 20 ቀናት" + # week(s) + assert self.locale._format_timeframe("week", 1) == "በአንድ ሳምንት" + assert self.locale._format_timeframe("week", -1) == "ከአንድ ሳምንት" + assert self.locale._format_timeframe("weeks", 7) == "በ 7 ሳምንታት" + assert self.locale._format_timeframe("weeks", -20) == "ከ 20 ሳምንታት" + # month(s) + assert self.locale._format_timeframe("month", 1) == "በአንድ ወር" + assert self.locale._format_timeframe("month", -1) == "ከአንድ ወር" + assert self.locale._format_timeframe("months", 7) == "በ 7 ወራት" + assert self.locale._format_timeframe("months", -20) == "ከ 20 ወር" + # year(s) + assert self.locale._format_timeframe("year", 1) == "በአንድ አመት" + assert self.locale._format_timeframe("year", -1) == "ከአንድ አመት" + assert self.locale._format_timeframe("years", 7) == "በ 7 ዓመታት" + assert self.locale._format_timeframe("years", -20) == "ከ 20 ዓመታት" + + def test_describe_am(self): + assert self.locale.describe("second", only_distance=True) == "አንድ ሰከንድ" + assert ( + self.locale.describe("second", only_distance=False) == "በአንድ ሰከንድ ውስጥ" + ) # (in) a second + + assert self.locale.describe("minute", only_distance=True) == "አንድ ደቂቃ" + assert ( + self.locale.describe("minute", only_distance=False) == "በአንድ ደቂቃ ውስጥ" + ) # (in) a minute + + def test_format_relative_now(self): + result = self.locale._format_relative("አሁን", "now", 0) + assert result == "አሁን" + + def test_ordinal_number(self): + assert self.locale.ordinal_number(1) == "1ኛ" + + def test_format_relative_future(self): + + result = self.locale._format_relative("በአንድ ሰዓት", "hour", 1) + + assert result == "በአንድ ሰዓት ውስጥ" # (in) one hour + + def test_format_relative_past(self): + + result = self.locale._format_relative("ከአንድ ሰዓት", "hour", -1) + + assert result == "ከአንድ ሰዓት በፊት" # an hour ago + + def test_weekday(self): + dt = arrow.Arrow(2015, 4, 11, 17, 30, 00) + assert self.locale.day_name(dt.isoweekday()) == "ቅዳሜ" + assert self.locale.day_abbreviation(dt.isoweekday()) == "ዓ"