@@ -358,7 +358,7 @@ def ab_datetime_now() -> AirbyteDateTime:
358358 return AirbyteDateTime .from_datetime (datetime .now (timezone .utc ))
359359
360360
361- def ab_datetime_parse (dt_str : str | int ) -> AirbyteDateTime :
361+ def ab_datetime_parse (dt_str : str | int , formats : list [ str ] | None = None , disallow_other_formats : bool = False ) -> AirbyteDateTime :
362362 """Parses a datetime string or timestamp into an AirbyteDateTime with timezone awareness.
363363
364364 This implementation is as flexible as possible to handle various datetime formats.
@@ -374,6 +374,10 @@ def ab_datetime_parse(dt_str: str | int) -> AirbyteDateTime:
374374 Args:
375375 dt_str: A datetime string in ISO8601/RFC3339 format, Unix timestamp (int/str),
376376 or other recognizable datetime format.
377+ formats: Optional list of format strings to try before falling back to more
378+ forgiving parsing logic. If provided, these formats will be tried in order.
379+ disallow_other_formats: If True, only the provided formats will be used for parsing,
380+ and more forgiving parsing logic will not be attempted.
377381
378382 Returns:
379383 AirbyteDateTime: A timezone-aware datetime object.
@@ -388,6 +392,8 @@ def ab_datetime_parse(dt_str: str | int) -> AirbyteDateTime:
388392 '2023-03-14T15:00:00+00:00'
389393 >>> ab_datetime_parse("2023-03-14") # Date-only
390394 '2023-03-14T00:00:00+00:00'
395+ >>> ab_datetime_parse("2023-03-14 15:09:26", formats=["%Y-%m-%d %H:%M:%S"])
396+ '2023-03-14T15:09:26+00:00'
391397 """
392398 try :
393399 # Handle numeric values as Unix timestamps (UTC)
@@ -408,6 +414,20 @@ def ab_datetime_parse(dt_str: str | int) -> AirbyteDateTime:
408414 f"Could not parse datetime string: expected string or integer, got { type (dt_str )} "
409415 )
410416
417+ if formats :
418+ for format_str in formats :
419+ try :
420+ parsed = datetime .strptime (dt_str , format_str )
421+ if parsed .tzinfo is None :
422+ parsed = parsed .replace (tzinfo = timezone .utc )
423+ return AirbyteDateTime .from_datetime (parsed )
424+ except ValueError :
425+ continue
426+
427+ if disallow_other_formats :
428+ raise ValueError (f"Could not parse datetime string '{ dt_str } ' with any of the provided formats: { formats } " )
429+
430+
411431 # Handle date-only format first
412432 if ":" not in dt_str and dt_str .count ("-" ) == 2 and "/" not in dt_str :
413433 try :
@@ -442,21 +462,30 @@ def ab_datetime_parse(dt_str: str | int) -> AirbyteDateTime:
442462 raise ValueError (f"Could not parse datetime string: { dt_str } " )
443463
444464
445- def ab_datetime_try_parse (dt_str : str ) -> AirbyteDateTime | None :
465+ def ab_datetime_try_parse (dt_str : str | int , formats : list [ str ] | None = None , disallow_other_formats : bool = False ) -> AirbyteDateTime | None :
446466 """Try to parse the input as a datetime, failing gracefully instead of raising an exception.
447467
448468 This is a thin wrapper around `ab_datetime_parse()` that catches parsing errors and
449469 returns `None` instead of raising an exception.
450470 The implementation is as flexible as possible to handle various datetime formats.
451471 Always returns a timezone-aware datetime (defaults to `UTC` if no timezone specified).
452472
473+ Args:
474+ dt_str: A datetime string in ISO8601/RFC3339 format, Unix timestamp (int/str),
475+ or other recognizable datetime format.
476+ formats: Optional list of format strings to try before falling back to more
477+ forgiving parsing logic. If provided, these formats will be tried in order.
478+ disallow_other_formats: If True, only the provided formats will be used for parsing,
479+ and more forgiving parsing logic will not be attempted.
480+
453481 Example:
454482 >>> ab_datetime_try_parse("2023-03-14T15:09:26Z") # Returns AirbyteDateTime
455483 >>> ab_datetime_try_parse("2023-03-14 15:09:26Z") # Missing 'T' delimiter still parsable
456484 >>> ab_datetime_try_parse("2023-03-14") # Returns midnight UTC time
485+ >>> ab_datetime_try_parse("2023-03-14 15:09:26", formats=["%Y-%m-%d %H:%M:%S"]) # Using specific format
457486 """
458487 try :
459- return ab_datetime_parse (dt_str )
488+ return ab_datetime_parse (dt_str , formats = formats , disallow_other_formats = disallow_other_formats )
460489 except (ValueError , TypeError ):
461490 return None
462491
0 commit comments