diff --git a/tests/time_converter/test_utc_time_parser.py b/tests/time_converter/test_utc_time_parser.py index b72a5a9..b1ed64a 100644 --- a/tests/time_converter/test_utc_time_parser.py +++ b/tests/time_converter/test_utc_time_parser.py @@ -14,9 +14,18 @@ @pytest.mark.parametrize( ("text", "timezone_label", "hour", "minute"), [ + ("10:00 utc", "UTC", 10, 0), ("10:00 UTC", "UTC", 10, 0), ("10:00UTC", "UTC", 10, 0), ("10 UTC", "UTC", 10, 0), + ("10:00 (UTC)", "UTC", 10, 0), + ("10:00 (UTC)abc", "UTC", 10, 0), + ("10:00 (UTC)+3", "UTC", 10, 0), + ("10:00 (UTC)-3", "UTC", 10, 0), + ("10:00 (UTC),", "UTC", 10, 0), + ("10:00 (UTC).", "UTC", 10, 0), + ("some text 10:00 (UTC)", "UTC", 10, 0), + ("some text 10:00 (UTC)abc", "UTC", 10, 0), ("10:30 cet", "CET", 10, 30), ("10 CEST", "CEST", 10, 0), ("10:45kyiv", "KYIV", 10, 45), @@ -94,6 +103,20 @@ def test_parse_utc_time_from_text_skips_non_utc_matches() -> None: assert parsed_datetime.minute == 0 +def test_parse_parenthesized_utc_time_from_long_message() -> None: + message_text = ( + "Some announcement text before the schedule. Trading starts at " + "10:00 (UTC). Additional unrelated text follows after the time." + ) + + parsed_times = parse_times_from_text(message_text, limit=5) + + assert len(parsed_times) == 1 + assert parsed_times[0].timezone_label == "UTC" + assert parsed_times[0].source_datetime.hour == 10 + assert parsed_times[0].source_datetime.minute == 0 + + @pytest.mark.parametrize( "text", [ diff --git a/time_converter/utc_time_parser.py b/time_converter/utc_time_parser.py index ed3b918..fbf2859 100644 --- a/time_converter/utc_time_parser.py +++ b/time_converter/utc_time_parser.py @@ -13,8 +13,9 @@ # Time parsing NAMED_TIME_PATTERN: Final[re.Pattern[str]] = re.compile( r"(?(?:[01]?\d|2[0-3]))" - r"(?::(?P[0-5]\d))? ?(?PUTC|CEST|CET|KYIV)\b" - r"(?![+-])", + r"(?::(?P[0-5]\d))?" + r"(?: ?(?PUTC|CEST|CET|KYIV)\b(?![+-])" + r"| ?\((?PUTC|CEST|CET|KYIV)\))", flags=re.IGNORECASE, ) OFFSET_TIME_PATTERN: Final[re.Pattern[str]] = re.compile( @@ -41,7 +42,9 @@ def _parse_named_time_match(match: re.Match[str]) -> Optional[ParsedTime]: hour = int(match.group("hour")) minute_group = match.group("minute") minute = int(minute_group) if minute_group is not None else 0 - timezone_label = match.group("timezone").upper() + timezone_label = ( + match.group("timezone") or match.group("parenthesized_timezone") + ).upper() timezone = TIMEZONES_BY_LABEL[timezone_label] return ParsedTime(