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
- 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.
- If the column holds epoch integers, cast explicitly: s.cast(pl.Datetime('ms')) (or convert the datetime with int(dt.timestamp() * 1000)).
- If the column holds strings, parse it first: s.str.to_datetime() then compare.
- 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
- Match Python types to column dtypes: date for pl.Date, datetime for pl.Datetime.
- Use .date() when comparing datetime.now() against Date columns, or cast the column to Datetime.
- Prefer pl.lit(...) literals so polars applies dtype-aware coercion and errors.
- Parse CSV date columns with explicit dtypes (str.to_datetime / str.to_date) matching the values you will compare against.
- Add dtype assertions in tests around comparison logic.
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
- cannot construct PySeries for type
- cannot convert DataFrame to
- cannot convert List column
- cannot convert Python type
- cannot do arithmetic with Series of dtype
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)