@@ -51,6 +51,63 @@ def test_now():
5151@pytest .mark .parametrize (
5252 "input_value,expected_output,error_type,error_match" ,
5353 [
54+ # Valid formats - must have T delimiter and timezone
55+ ("2023-03-14T15:09:26+00:00" , "2023-03-14T15:09:26+00:00" , None , None ), # Basic UTC format
56+ (
57+ "2023-03-14T15:09:26.123+00:00" ,
58+ "2023-03-14T15:09:26.123000+00:00" ,
59+ None ,
60+ None ,
61+ ), # With milliseconds
62+ (
63+ "2023-03-14T15:09:26.123456+00:00" ,
64+ "2023-03-14T15:09:26.123456+00:00" ,
65+ None ,
66+ None ,
67+ ), # With microseconds
68+ (
69+ "2023-03-14T15:09:26-04:00" ,
70+ "2023-03-14T15:09:26-04:00" ,
71+ None ,
72+ None ,
73+ ), # With timezone offset
74+ ("2023-03-14T15:09:26Z" , "2023-03-14T15:09:26+00:00" , None , None ), # With Z timezone
75+ (
76+ "2023-03-14T00:00:00+00:00" ,
77+ "2023-03-14T00:00:00+00:00" ,
78+ None ,
79+ None ,
80+ ), # Full datetime with zero time
81+ (
82+ "2023-03-14T15:09:26GMT" ,
83+ "2023-03-14T15:09:26+00:00" ,
84+ None ,
85+ None ,
86+ ), # Non-standard timezone name ok
87+ (
88+ "2023-03-14T15:09:26" ,
89+ "2023-03-14T15:09:26+00:00" ,
90+ None ,
91+ None ,
92+ ), # Missing timezone, assume UTC
93+ (
94+ "2023-03-14 15:09:26" ,
95+ "2023-03-14T15:09:26+00:00" ,
96+ None ,
97+ None ,
98+ ), # Missing T delimiter ok, assume UTC
99+ (
100+ "2023-03-14" ,
101+ "2023-03-14T00:00:00+00:00" ,
102+ None ,
103+ None ,
104+ ), # Date only, missing time and timezone
105+ (
106+ "2023/03/14T15:09:26Z" ,
107+ "2023-03-14T15:09:26+00:00" ,
108+ None ,
109+ None ,
110+ ), # Wrong date separator, ok
54111 # Valid formats
55112 ("2023-03-14T15:09:26Z" , "2023-03-14T15:09:26+00:00" , None , None ),
56113 ("2023-03-14T15:09:26-04:00" , "2023-03-14T15:09:26-04:00" , None , None ),
@@ -71,20 +128,10 @@ def test_now():
71128 ("2023-12-32" , None , ValueError , "Invalid date format: 2023-12-32" ),
72129 ("2023-00-14" , None , ValueError , "Invalid date format: 2023-00-14" ),
73130 ("2023-12-00" , None , ValueError , "Invalid date format: 2023-12-00" ),
74- # Invalid separators and formats
75- ("2023/12/14" , None , ValueError , "Could not parse datetime string: 2023/12/14" ),
76- (
77- "2023-03-14 15:09:26Z" ,
78- None ,
79- ValueError ,
80- "Could not parse datetime string: 2023-03-14 15:09:26Z" ,
81- ),
82- (
83- "2023-03-14T15:09:26GMT" ,
84- None ,
85- ValueError ,
86- "Could not parse datetime string: 2023-03-14T15:09:26GMT" ,
87- ),
131+ # Non-standard separators and formats, ok
132+ ("2023/12/14" , "2023-12-14T00:00:00+00:00" , None , None ),
133+ ("2023-03-14 15:09:26Z" , "2023-03-14T15:09:26+00:00" , None , None ),
134+ ("2023-03-14T15:09:26GMT" , "2023-03-14T15:09:26+00:00" , None , None ),
88135 # Invalid time components
89136 (
90137 "2023-03-14T25:09:26Z" ,
@@ -105,16 +152,24 @@ def test_now():
105152 "Could not parse datetime string: 2023-03-14T15:09:99Z" ,
106153 ),
107154 ],
155+ # ("invalid datetime", None), # Completely invalid
156+ # ("15:09:26Z", None), # Missing date component
157+ # ("2023-03-14T25:09:26Z", None), # Invalid hour
158+ # ("2023-03-14T15:99:26Z", None), # Invalid minute
159+ # ("2023-03-14T15:09:99Z", None), # Invalid second
160+ # ("2023-02-30T00:00:00Z", None), # Impossible date
108161)
109162def test_parse (input_value , expected_output , error_type , error_match ):
110163 """Test parsing various datetime string formats."""
111164 if error_type :
112165 with pytest .raises (error_type , match = error_match ):
113166 ab_datetime_parse (input_value )
167+ assert not ab_datetime_try_parse (input_value )
114168 else :
115169 dt = ab_datetime_parse (input_value )
116170 assert isinstance (dt , AirbyteDateTime )
117171 assert str (dt ) == expected_output
172+ assert ab_datetime_try_parse (input_value ) and ab_datetime_try_parse (input_value ) == dt
118173
119174
120175@pytest .mark .parametrize (
@@ -194,42 +249,6 @@ def test_operator_overloading():
194249 _ = "invalid" - dt
195250
196251
197- @pytest .mark .parametrize (
198- "input_value,expected_output" ,
199- [
200- # Valid formats - must have T delimiter and timezone
201- ("2023-03-14T15:09:26+00:00" , "2023-03-14T15:09:26+00:00" ), # Basic UTC format
202- ("2023-03-14T15:09:26.123+00:00" , "2023-03-14T15:09:26.123000+00:00" ), # With milliseconds
203- (
204- "2023-03-14T15:09:26.123456+00:00" ,
205- "2023-03-14T15:09:26.123456+00:00" ,
206- ), # With microseconds
207- ("2023-03-14T15:09:26-04:00" , "2023-03-14T15:09:26-04:00" ), # With timezone offset
208- ("2023-03-14T15:09:26Z" , "2023-03-14T15:09:26+00:00" ), # With Z timezone
209- ("2023-03-14T00:00:00+00:00" , "2023-03-14T00:00:00+00:00" ), # Full datetime with zero time
210- # Invalid formats - reject anything without proper ISO8601/RFC3339 format
211- ("invalid datetime" , None ), # Completely invalid
212- ("2023-03-14 15:09:26" , None ), # Missing T delimiter
213- ("2023-03-14" , None ), # Date only, missing time and timezone
214- ("15:09:26Z" , None ), # Missing date component
215- ("2023-03-14T15:09:26" , None ), # Missing timezone
216- ("2023-03-14T15:09:26GMT" , None ), # Invalid timezone format
217- ("2023/03/14T15:09:26Z" , None ), # Wrong date separator
218- ("2023-03-14T25:09:26Z" , None ), # Invalid hour
219- ("2023-03-14T15:99:26Z" , None ), # Invalid minute
220- ("2023-03-14T15:09:99Z" , None ), # Invalid second
221- ],
222- )
223- def test_ab_datetime_try_parse (input_value , expected_output ):
224- """Test datetime string format validation."""
225- result = ab_datetime_try_parse (input_value )
226- if expected_output is None :
227- assert result is None
228- else :
229- assert isinstance (result , AirbyteDateTime )
230- assert str (result ) == expected_output
231-
232-
233252def test_epoch_millis ():
234253 """Test Unix epoch millisecond timestamp conversion methods."""
235254 # Test to_epoch_millis()
0 commit comments