pola-rs/polars · error

cannot compare datetime.datetime to Series of type {self.dty

Error message

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

What it means

Raised in Series._comp (py-polars/src/polars/series/series.py:878) when comparing against a datetime.datetime scalar but the Series dtype is neither Date nor Datetime. Polars has special-cased comparison paths for date/datetime/time/timedelta scalars; a datetime falls into that dispatcher, and if the Series holds e.g. Int64, String, or Duration, the combination is meaningless and rejected with ValueError naming the actual dtype.

Source

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

            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 df599052da)

Solutions

  1. Convert the Series to Datetime first: s.cast(pl.Datetime) or s.str.to_datetime() for strings, or pl.from_epoch(s, time_unit="ms") for integers
  2. If the scalar side is wrong (you meant a date/time/duration), use the matching Python type so the correct branch is taken
  3. Add schema validation after ingestion so dtype surprises surface before comparison logic

Example fix

# before
s = pl.Series(["2024-01-01", "2024-06-01"])  # strings
s > datetime(2024, 3, 1)  # ValueError

# after
s = s.str.to_datetime()
s > datetime(2024, 3, 1)
# for epoch ints: s = pl.from_epoch(s, time_unit="s").cast(pl.Datetime("us"))
Defensive patterns

Strategy: validation

Validate before calling

import polars as pl
from datetime import datetime

def comparable_to_datetime(s: pl.Series) -> bool:
    return s.dtype in (pl.Date, pl.Datetime) or (isinstance(s.dtype, pl.Datetime))

if not comparable_to_datetime(s):
    raise TypeError(f"{s.dtype} Series cannot be compared to datetime; cast first")

Type guard

def is_temporal_series(s: pl.Series) -> bool:
    return s.dtype.base_type() in (pl.Date, pl.Datetime)

Try / catch

try:
    mask = s > cutoff
except ValueError as e:
    if "cannot compare datetime.datetime" in str(e):
        s = s.str.to_datetime() if s.dtype == pl.String else s.cast(pl.Datetime)
        mask = s > cutoff
    else:
        raise

Prevention

When it happens

Trigger: pl.Series([1, 2, 3]) < datetime(2024, 1, 1); pl.Series(["a"]).eq(datetime.now()); comparing a Duration or Time Series to a datetime instance.

Common situations: Type drift: a column expected to be Datetime was parsed as String/Int (e.g. CSV ingestion without schema hints, or epoch integers not converted); unit tests comparing the wrong series; mixing up time and datetime objects.

Related errors


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