pola-rs/polars · error · ValueError

cannot compare datetime.datetime to Series of type

Error message

cannot compare datetime.datetime to Series of type {self.dtype}

What it means

In _comp, when the other operand is a datetime.datetime, Polars only supports comparing it against a Series whose dtype is Datetime; for any other dtype (Date, Int64, Utf8, etc.) it raises ValueError. A datetime.datetime is not interchangeable with a date or integer, and Polars refuses the implicit cross-type comparison.

Solutions

  1. If the Series dtype is Date, compare with a datetime.date instead: datetime.now().date(), or cast the Series: s.cast(pl.Datetime) then compare with the datetime.
  2. If the column holds epoch integers, cast explicitly: s.cast(pl.Datetime('ms')) (or convert the datetime with int(dt.timestamp() * 1000)).
  3. If the column holds strings, parse it first: s.str.to_datetime() then compare.
  4. Prefer pl.lit(...) on the Polars side, which produces clearer dtype-aware comparison behavior than raw Python objects.

Example fix

// before
s = pl.Series('d', [date(2024, 1, 1)])  # dtype Date
s > datetime.now()  # ValueError: cannot compare datetime.datetime to Series of type Date

// after
s > datetime.now().date()  # compare date-to-date
# or: s.cast(pl.Datetime) > datetime.now()
Defensive patterns

Strategy: validation

Validate before calling

assert s.dtype in (pl.Date, pl.Datetime), f'unexpected dtype {s.dtype}'
if s.dtype == pl.Date and isinstance(py_value, datetime):
    py_value = py_value.date()  # or cast Series: s.cast(pl.Datetime)

Type guard

def comparable_py_type(dtype: pl.DataType):
    import datetime as _dt
    return _dt.date if dtype == pl.Date else _dt.datetime

Try / catch

try:
    result = s > dt
except ValueError as e:
    if 'cannot compare datetime.datetime' in str(e):
        result = (s.cast(pl.Datetime) > dt) if s.dtype == pl.Date else (s > dt.date())
    else:
        raise

Prevention

When it happens

Trigger: Comparing a Date-typed Series with a datetime.datetime (very common: reading a date column then comparing to datetime.now()); comparing Int64/Utf8 columns holding epoch millis or ISO strings against datetime objects, via ==, !=, <, >, <=, >=.

Common situations: datetime.now() returning a datetime while the column was parsed as pl.Date (e.g. from a 'YYYY-MM-DD' CSV column); comparing raw epoch-integer columns against datetimes without casting; forgetting .date() on a datetime before comparing to a Date column.

Related errors


AI-assisted analysis of pola-rs/polars@fe841f959e (2026-09-18). Data as JSON: /api/errors/9fb10f4194706d30. Report an issue: GitHub.

Appendix: source

Thrown at py-polars/src/polars/series/series.py:764

            f = get_ffi_func(op + "_<>", Float64, self._s)
            assert f is not None
            return self._from_pyseries(f(other))

        elif isinstance(other, datetime):
            if self.dtype == Date:
                # require upcast when comparing date series to datetime
                self = self.cast(Datetime("us"))
                time_unit = "us"
            elif self.dtype == Datetime:
                # Use local time zone info
                time_zone = self.dtype.time_zone  # type: ignore[attr-defined]
                if str(other.tzinfo) != str(time_zone):
                    msg = f"datetime time zone {other.tzinfo!r} does not match Series timezone {time_zone!r}"
                    raise TypeError(msg)
                time_unit = self.dtype.time_unit  # type: ignore[attr-defined]
            else:
                msg = f"cannot compare datetime.datetime to Series of type {self.dtype}"
                raise ValueError(msg)
            ts = datetime_to_int(other, time_unit)  # type: ignore[arg-type]
            f = get_ffi_func(op + "_<>", Int64, self._s)
            assert f is not None
            return self._from_pyseries(f(ts))

        elif isinstance(other, time) and self.dtype == Time:
            d = time_to_int(other)
            f = get_ffi_func(op + "_<>", Int64, self._s)
            assert f is not None
            return self._from_pyseries(f(d))

        elif isinstance(other, timedelta) and self.dtype == Duration:
            time_unit = self.dtype.time_unit  # type: ignore[attr-defined]
            td = timedelta_to_int(other, time_unit)
            f = get_ffi_func(op + "_<>", Int64, self._s)
            assert f is not None
            return self._from_pyseries(f(td))

View on GitHub (pinned to fe841f959e)