diff --git a/singer_sdk/streams/core.py b/singer_sdk/streams/core.py index 3f8ca6a72..739c254d8 100644 --- a/singer_sdk/streams/core.py +++ b/singer_sdk/streams/core.py @@ -365,6 +365,23 @@ def _write_replication_key_signpost( state = self.get_context_state(context) write_replication_key_signpost(state, value) + def _parse_datetime(self, value: str) -> datetime.datetime: # noqa: PLR6301 + """Parse a datetime string. + + Args: + value: The datetime string. + + Returns: + The parsed datetime, timezone-aware preferred. + """ + result = datetime_fromisoformat(value) + + # Ensure datetime is timezone-aware + if not result.tzinfo: + result = result.astimezone() + + return result + def compare_start_date(self, value: str, start_date_value: str) -> str: """Compare a bookmark value to a start date and return the most recent value. @@ -384,7 +401,7 @@ def compare_start_date(self, value: str, start_date_value: str) -> str: The most recent value between the bookmark and start date. """ if self.is_timestamp_replication_key: - return max(value, start_date_value, key=datetime_fromisoformat) + return max(value, start_date_value, key=self._parse_datetime) return value diff --git a/tests/core/test_streams.py b/tests/core/test_streams.py index 592f921e6..1a25defac 100644 --- a/tests/core/test_streams.py +++ b/tests/core/test_streams.py @@ -141,6 +141,18 @@ def test_stream_apply_catalog(stream: Stream): parse(CONFIG_START_DATE).replace(tzinfo=datetime.timezone.utc), id="datetime-repl-key-old-bookmark", ), + pytest.param( + "test", + None, + "2021-01-02T00:00:00-08:00", + datetime.datetime( + 2021, + 1, + 2, + tzinfo=datetime.timezone(datetime.timedelta(hours=-8)), + ), + id="datetime-repl-key-recent-bookmark-tz-aware", + ), pytest.param( "unix_ts", None,