@@ -263,12 +263,9 @@ def assert_equal(
263263 for col , value in object_sentinel_values .items ():
264264 try :
265265 # can't use `isinstance()` here - https://stackoverflow.com/a/68743663/1707525
266- if type (value ) is datetime .date :
267- expected [col ] = pd .to_datetime (expected [col ]).dt .date
268- elif type (value ) is datetime .time :
269- expected [col ] = pd .to_datetime (expected [col ]).dt .time
270- elif type (value ) is datetime .datetime :
271- expected [col ] = pd .to_datetime (expected [col ]).dt .to_pydatetime ()
266+ value_type = type (value )
267+ if value_type in (datetime .date , datetime .time , datetime .datetime ):
268+ expected [col ] = _parse_expected_datetime_column (expected [col ], value_type )
272269 except Exception as e :
273270 from sqlmesh .core .console import get_console
274271
@@ -1014,6 +1011,34 @@ def _raise_error(msg: str, path: Path | None = None) -> None:
10141011 raise TestError (f"Failed to run test:\n { msg } " )
10151012
10161013
1014+ def _parse_expected_datetime_column (series : pd .Series , target_type : type ) -> pd .Series :
1015+ """Convert a series of expected values to python ``date``/``time``/``datetime``.
1016+
1017+ Falls back to microsecond resolution when pandas' default nanosecond
1018+ parsing overflows. SQL ``TIMESTAMP`` columns can carry values outside
1019+ pandas' default ``datetime64[ns]`` range (1677-09-21..2262-04-11), so
1020+ unit tests may compare against values like ``0001-01-01`` which are
1021+ valid in the database but overflow the default resolution.
1022+ """
1023+ import pandas as pd
1024+ from pandas .errors import OutOfBoundsDatetime
1025+
1026+ try :
1027+ parsed = pd .to_datetime (series )
1028+ except OutOfBoundsDatetime :
1029+ parsed = series .astype ("datetime64[us]" )
1030+
1031+ if target_type is datetime .date :
1032+ return parsed .dt .date
1033+ if target_type is datetime .time :
1034+ return parsed .dt .time
1035+ # `Series.dt.to_pydatetime()` returns an `ndarray` in pandas 2.x. Wrap it in a
1036+ # Series with ``dtype=object`` so pandas does not coerce the values back to
1037+ # ``pd.Timestamp`` (which would reintroduce the nanosecond overflow this
1038+ # function exists to avoid).
1039+ return pd .Series (parsed .dt .to_pydatetime (), index = parsed .index , dtype = "object" )
1040+
1041+
10171042def _normalize_df_value (value : t .Any ) -> t .Any :
10181043 """Normalize data in a pandas dataframe so ruamel and sqlglot can deal with it."""
10191044 import numpy as np
0 commit comments