@@ -19,20 +19,28 @@ def _parse_sql_datetime(value: str) -> datetime:
1919 ODBC/older Python runtimes deliver datetime2 values as strings without a
2020 ``T`` separator and often carry seven fractional digits (100ns precision),
2121 e.g. ``'2026-08-09 05:25:26.5205700'``. Python's ``datetime.fromisoformat``
22- rejects values with more than six fractional digits on Python < 3.13 , so
23- normalize the string first: normalize the separator, then drop any
24- fractional component beyond six digits.
22+ only accepts three or six fractional digits on Python < 3.11 , so normalize
23+ the string first: restore the ``T`` separator and pad the fractional
24+ component to exactly six digits.
2525 """
2626 normalized = value .replace ('Z' , '+00:00' )
2727 if 'T' not in normalized :
2828 head , sep , rest = normalized .partition (' ' )
2929 if sep :
3030 normalized = f"{ head } T{ rest } "
31- if '.' in normalized :
32- head , sep , frac = normalized .rpartition ('.' )
33- frac = frac .rstrip ('0' )[:6 ]
34- if frac :
35- normalized = f"{ head } .{ frac } "
31+ dot_pos = normalized .rfind ('.' )
32+ if dot_pos != - 1 :
33+ suffix = ''
34+ frac_end = len (normalized )
35+ for marker in ('+' , '-' ):
36+ idx = normalized .find (marker , dot_pos + 1 )
37+ if idx != - 1 :
38+ frac_end = idx
39+ suffix = normalized [idx :]
40+ break
41+ frac = normalized [dot_pos + 1 :frac_end ]
42+ frac = frac [:6 ].ljust (6 , '0' )
43+ normalized = f"{ normalized [:dot_pos ]} .{ frac } { suffix } "
3644 result = datetime .fromisoformat (normalized )
3745 if result .tzinfo is None :
3846 return result .replace (tzinfo = timezone .utc )
0 commit comments