diff --git a/src/apify_client/_http_clients/_base.py b/src/apify_client/_http_clients/_base.py index 507ae432..7683fdfb 100644 --- a/src/apify_client/_http_clients/_base.py +++ b/src/apify_client/_http_clients/_base.py @@ -157,7 +157,9 @@ def _parse_params(params: dict[str, Any] | None) -> dict[str, Any] | None: elif isinstance(value, list): parsed_params[key] = ','.join(value) elif isinstance(value, datetime): - utc_aware_dt = value.astimezone(UTC) + # Treat a naive datetime as UTC; `.astimezone()` would otherwise assume the host's local tz. + aware = value.replace(tzinfo=UTC) if value.tzinfo is None else value + utc_aware_dt = aware.astimezone(UTC) iso_str = utc_aware_dt.isoformat(timespec='milliseconds') parsed_params[key] = iso_str.replace('+00:00', 'Z') elif value is not None: diff --git a/tests/unit/test_http_clients.py b/tests/unit/test_http_clients.py index 93e942bd..b18fb762 100644 --- a/tests/unit/test_http_clients.py +++ b/tests/unit/test_http_clients.py @@ -201,6 +201,21 @@ def test_parse_params_datetime() -> None: assert result == {'created_at': '2024-01-15T10:30:45.123Z'} +@pytest.mark.skipif(not hasattr(time, 'tzset'), reason='time.tzset is Unix-only') +def test_parse_params_naive_datetime_treated_as_utc(monkeypatch: pytest.MonkeyPatch) -> None: + """Naive datetimes must be treated as UTC, not the host's local timezone.""" + monkeypatch.setenv('TZ', 'Asia/Karachi') + time.tzset() + try: + dt = datetime(2024, 1, 15, 10, 30, 45, 123000) # noqa: DTZ001 -- intentionally naive + result = HttpClient._parse_params({'created_at': dt}) + assert result == {'created_at': '2024-01-15T10:30:45.123Z'} + finally: + # Restore TZ before re-applying tzset so the test doesn't leak Karachi time to later tests. + monkeypatch.undo() + time.tzset() + + def test_parse_params_none_values_filtered() -> None: """Test _parse_params filters out None values.""" result = HttpClient._parse_params({'a': 1, 'b': None, 'c': 'value'})