diff --git a/sqlmesh/utils/date.py b/sqlmesh/utils/date.py index 5358719abe..f8df65c352 100644 --- a/sqlmesh/utils/date.py +++ b/sqlmesh/utils/date.py @@ -194,7 +194,13 @@ def to_datetime( try: dt = datetime.strptime(str(value), DATE_INT_FMT) except ValueError: - dt = datetime.fromtimestamp(epoch / 1000.0, tz=UTC) + try: + dt = datetime.fromtimestamp(epoch / 1000.0, tz=UTC) + except (OverflowError, OSError, ValueError): + # A non-finite or out-of-range epoch (e.g. "inf", 1e30, or a + # huge millis value) overflows fromtimestamp. Fall through to + # the ValueError below rather than leaking OverflowError/OSError. + dt = None if dt is None: raise ValueError(f"Could not convert `{value}` to datetime.") diff --git a/tests/utils/test_date.py b/tests/utils/test_date.py index bbd5bdf63a..c926507ccd 100644 --- a/tests/utils/test_date.py +++ b/tests/utils/test_date.py @@ -41,6 +41,17 @@ def test_to_datetime() -> None: assert to_datetime("31536000000") == target +@pytest.mark.parametrize( + "value", + ["inf", "-inf", "1e30", "99999999999999999999", float("inf")], +) +def test_to_datetime_out_of_range_raises(value: t.Any) -> None: + # A non-finite or out-of-range epoch overflows fromtimestamp; it must raise + # the documented ValueError rather than leaking OverflowError/OSError. + with pytest.raises(ValueError): + to_datetime(value) + + @pytest.mark.parametrize( "expression, result", [