diff --git a/airbyte_cdk/sources/declarative/interpolation/macros.py b/airbyte_cdk/sources/declarative/interpolation/macros.py index dc77744dc..f84ece214 100644 --- a/airbyte_cdk/sources/declarative/interpolation/macros.py +++ b/airbyte_cdk/sources/declarative/interpolation/macros.py @@ -177,6 +177,8 @@ def format_datetime( dt_datetime = ( datetime.datetime.strptime(dt, input_format) if input_format else str_to_datetime(dt) ) + if dt_datetime.tzinfo is None: + dt_datetime = dt_datetime.replace(tzinfo=pytz.utc) return DatetimeParser().format(dt=dt_datetime, format=format) diff --git a/airbyte_cdk/sources/declarative/schema/default_schema_loader.py b/airbyte_cdk/sources/declarative/schema/default_schema_loader.py index a9b625e7d..f860d60fb 100644 --- a/airbyte_cdk/sources/declarative/schema/default_schema_loader.py +++ b/airbyte_cdk/sources/declarative/schema/default_schema_loader.py @@ -37,7 +37,7 @@ def get_json_schema(self) -> Mapping[str, Any]: try: return self.default_loader.get_json_schema() - except OSError: + except (OSError, ValueError): # A slight hack since we don't directly have the stream name. However, when building the default filepath we assume the # runtime options stores stream name 'name' so we'll do the same here stream_name = self._parameters.get("name", "") diff --git a/unit_tests/sources/declarative/interpolation/test_macros.py b/unit_tests/sources/declarative/interpolation/test_macros.py index aec265533..cd42f9d08 100644 --- a/unit_tests/sources/declarative/interpolation/test_macros.py +++ b/unit_tests/sources/declarative/interpolation/test_macros.py @@ -101,6 +101,18 @@ def test_macros_export(test_name, fn_name, found_in_macros): "%ms", "2022-01-01T01:01:01Z", ), + ( + "2022-01-01T01:01:01+0100", + "%Y-%m-%dT%H:%M:%S.%f%z", + None, + "2022-01-01T00:01:01.000000+0000", + ), + ( + "2022-01-01T01:01:01", + "%Y-%m-%dT%H:%M:%S.%f%z", + None, + "2022-01-01T01:01:01.000000+0000", + ), ], ids=[ "test_datetime_string_to_date", @@ -117,6 +129,8 @@ def test_macros_export(test_name, fn_name, found_in_macros): "test_timestamp_to_format_string", "test_timestamp_epoch_microseconds_to_format_string", "test_timestamp_ms_to_format_string", + "test_datetime_with_timezone", + "test_datetime_without_timezone_then_utc_is_inferred", ], ) def test_format_datetime(input_value, format, input_format, expected_output):