From 49ead83eae1eb494851fbf1660fbd97cb2cf9742 Mon Sep 17 00:00:00 2001 From: autumn_atlas <3477314+Autumn-Atlas@users.noreply.github.com> Date: Wed, 30 Sep 2026 13:14:11 +0800 Subject: [PATCH] fix(examples): parse the live API's published timestamps on Python 3.8-3.10 The Search API sends `published` as "2026-09-30 05:04:18 +0000". datetime.fromisoformat only accepts that on Python 3.11+, so on 3.8-3.10 the company news monitor's live mode stopped at the first real article with "news item published must be an RFC 3339 timestamp". The checked-in fixtures use RFC 3339 ("...Z"), so the tests never saw the live format. Fall back to strptime("%Y-%m-%d %H:%M:%S %z") and test both formats. Verified against the live API on Python 3.10: before, the error above; after, 5 matching articles in the report. Co-Authored-By: Claude Opus 5.5 --- examples/company_news_monitor/monitor.py | 11 +++++++++-- tests/test_company_news_monitor_example.py | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/examples/company_news_monitor/monitor.py b/examples/company_news_monitor/monitor.py index f7b8388..5022020 100644 --- a/examples/company_news_monitor/monitor.py +++ b/examples/company_news_monitor/monitor.py @@ -56,13 +56,20 @@ def parse_args(): return parser.parse_args() +# The live API sends `published` as "2026-09-30 05:04:18 +0000". +API_TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S %z" + + def parse_timestamp(value, label): if not isinstance(value, str) or not value: raise ValueError("{} must be a non-empty RFC 3339 timestamp".format(label)) try: parsed = datetime.fromisoformat(value.replace("Z", "+00:00")) - except ValueError as exc: - raise ValueError("{} must be an RFC 3339 timestamp".format(label)) from exc + except ValueError: + try: + parsed = datetime.strptime(value, API_TIMESTAMP_FORMAT) + except ValueError as exc: + raise ValueError("{} must be an RFC 3339 timestamp".format(label)) from exc if parsed.tzinfo is None: raise ValueError("{} must include a timezone".format(label)) return parsed.astimezone(timezone.utc) diff --git a/tests/test_company_news_monitor_example.py b/tests/test_company_news_monitor_example.py index 031260b..7a63395 100644 --- a/tests/test_company_news_monitor_example.py +++ b/tests/test_company_news_monitor_example.py @@ -154,6 +154,25 @@ def test_date_boundaries_are_inclusive_and_outside_articles_are_removed(): } +@pytest.mark.parametrize( + "value", + ["2026-09-30 05:04:18 +0000", "2026-09-30 13:04:18 +0800", "2026-09-30T05:04:18Z"], +) +def test_parse_timestamp_accepts_live_api_published_format(value): + module = load_example_module() + + parsed = module.parse_timestamp(value, "published") + + assert parsed == datetime(2026, 9, 30, 5, 4, 18, tzinfo=timezone.utc) + + +def test_parse_timestamp_still_rejects_values_without_timezone(): + module = load_example_module() + + with pytest.raises(ValueError): + module.parse_timestamp("2026-09-30 05:04:18", "published") + + def test_same_url_with_optional_id_drift_is_reported_once(): module = load_example_module() start = datetime(2026, 8, 4, tzinfo=timezone.utc)