diff --git a/babel/dates.py b/babel/dates.py index 7b626aa11..d0372d143 100644 --- a/babel/dates.py +++ b/babel/dates.py @@ -1480,7 +1480,7 @@ def __getitem__(self, name: str) -> str: else: raise KeyError(f"Unsupported date/time field {char!r}") - def extract(self, char: str) -> int: + def extract(self, char: str) -> int | str: char = str(char)[0] if char == 'y': return self.value.year @@ -1496,6 +1496,12 @@ def extract(self, char: str) -> int: return self.value.minute elif char == 'a': return int(self.value.hour >= 12) # 0 for am, 1 for pm + elif char == 'G': + return int(self.value.year >= 0) # 0 for BCE, 1 for CE + elif char == 'B': + # The day period is rendered from the same identifier, + # so the extracted value matches what `format_period` renders. + return get_period_id(self.value, locale=self.locale) else: raise NotImplementedError( f"Not implemented: extracting {char!r} from {self.value!r}", diff --git a/tests/test_date_intervals.py b/tests/test_date_intervals.py index 33a85d38a..ee52b75c1 100644 --- a/tests/test_date_intervals.py +++ b/tests/test_date_intervals.py @@ -61,3 +61,32 @@ def test_issue_825(): locale='pt', ) assert formatted == '1 h' + + +@pytest.mark.parametrize( + ("start", "end", "skeleton", "expected"), + [ + # Era ('G') interval formats used to raise NotImplementedError when + # computing the greatest difference between the two instants. + # A year difference must select the 'y' pattern of the "Gy" interval format. + (TEST_DT, TEST_DT.replace(year=2017), "Gy", "2016\u2009\u2013\u20092017 AD"), + ( + TEST_DT, + TEST_DT.replace(year=2017, month=3), + "GyM", + "1/2016\u2009\u2013\u20093/2017 AD", + ), + # Day period ('B') interval formats used to raise NotImplementedError, too. + # Differing day periods must select the 'B' pattern of the "Bh" interval format. + ( + TEST_DT, + TEST_DT.replace(hour=16), + "Bh", + "11 in the morning\u2009\u2013\u20094 in the afternoon", + ), + # ... and a shared day period must fall through to the 'h' pattern. + (TEST_DT, TEST_DT.replace(hour=10), "Bh", "11\u2009\u2013\u200910 in the morning"), + ], +) +def test_format_interval_era_and_day_period(start, end, skeleton, expected): + assert dates.format_interval(start, end, skeleton, locale="en") == expected