Skip to content

Commit 49ead83

Browse files
Autumn-Atlasclaude
andcommitted
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 <noreply@anthropic.com>
1 parent 9d68eb1 commit 49ead83

2 files changed

Lines changed: 28 additions & 2 deletions

File tree

‎examples/company_news_monitor/monitor.py‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,20 @@ def parse_args():
5656
return parser.parse_args()
5757

5858

59+
# The live API sends `published` as "2026-09-30 05:04:18 +0000".
60+
API_TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S %z"
61+
62+
5963
def parse_timestamp(value, label):
6064
if not isinstance(value, str) or not value:
6165
raise ValueError("{} must be a non-empty RFC 3339 timestamp".format(label))
6266
try:
6367
parsed = datetime.fromisoformat(value.replace("Z", "+00:00"))
64-
except ValueError as exc:
65-
raise ValueError("{} must be an RFC 3339 timestamp".format(label)) from exc
68+
except ValueError:
69+
try:
70+
parsed = datetime.strptime(value, API_TIMESTAMP_FORMAT)
71+
except ValueError as exc:
72+
raise ValueError("{} must be an RFC 3339 timestamp".format(label)) from exc
6673
if parsed.tzinfo is None:
6774
raise ValueError("{} must include a timezone".format(label))
6875
return parsed.astimezone(timezone.utc)

‎tests/test_company_news_monitor_example.py‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,25 @@ def test_date_boundaries_are_inclusive_and_outside_articles_are_removed():
154154
}
155155

156156

157+
@pytest.mark.parametrize(
158+
"value",
159+
["2026-09-30 05:04:18 +0000", "2026-09-30 13:04:18 +0800", "2026-09-30T05:04:18Z"],
160+
)
161+
def test_parse_timestamp_accepts_live_api_published_format(value):
162+
module = load_example_module()
163+
164+
parsed = module.parse_timestamp(value, "published")
165+
166+
assert parsed == datetime(2026, 9, 30, 5, 4, 18, tzinfo=timezone.utc)
167+
168+
169+
def test_parse_timestamp_still_rejects_values_without_timezone():
170+
module = load_example_module()
171+
172+
with pytest.raises(ValueError):
173+
module.parse_timestamp("2026-09-30 05:04:18", "published")
174+
175+
157176
def test_same_url_with_optional_id_drift_is_reported_once():
158177
module = load_example_module()
159178
start = datetime(2026, 8, 4, tzinfo=timezone.utc)

0 commit comments

Comments
 (0)