pola-rs/polars · error

first cast to integer before dividing datelike dtypes

Error message

first cast to integer before dividing datelike dtypes

What it means

Raised by Series.__truediv__ when the left operand is a temporal Series (Date, Datetime, Time) that is not a Duration. Dividing a datelike value by a number has no well-defined unit-aware meaning in Polars, so the operation is refused outright instead of guessing an epoch scale. Duration is exempt because dividing a duration by a scalar (e.g. halving a timespan) is well defined.

Source

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

                return Array(convert_to_primitive(dtype.inner), shape=dtype.shape)
            if isinstance(dtype, List):
                return List(convert_to_primitive(dtype.inner))
            return leaf_dtype

        return self.cast(convert_to_primitive(self.dtype))

    @overload
    def __truediv__(self, other: Expr) -> Expr: ...

    @overload
    def __truediv__(self, other: Any) -> Series: ...

    def __truediv__(self, other: Any) -> Series | Expr:
        if isinstance(other, pl.Expr):
            return F.lit(self) / other
        if self.dtype.is_temporal() and not isinstance(self.dtype, Duration):
            msg = "first cast to integer before dividing datelike dtypes"
            raise TypeError(msg)
        if isinstance(other, (int, float)) and (
            self.dtype.is_decimal() or isinstance(self.dtype, Duration)
        ):
            return self.to_frame().select(F.col(self.name) / other).to_series()

        self = (
            self
            if (
                self.dtype.is_float()
                or self.dtype.is_decimal()
                or isinstance(self.dtype, (List, Array, Duration))
                or (
                    isinstance(other, Series) and isinstance(other.dtype, (List, Array))
                )
            )
            else self._recursive_cast_to_dtype(Float64())
        )

View on GitHub (pinned to df599052da)

Solutions

  1. Cast to integer first, then divide: `s.cast(pl.Int64) / n` (use the epoch value in the column's time unit for Datetime).
  2. Use the dt accessors for unit-aware math: `s.dt.total_days() / 7`, `s.dt.epoch('d') / n`, `s.dt.timestamp('ms') / 1_000`.
  3. If you meant duration math (e.g. split a timespan), convert to Duration first: `(end_dt - start_dt) / 2` works because Duration is exempt.
  4. If the column should never be temporal, fix the read/inference: `pl.read_csv(..., schema_overrides={'ts': pl.Int64})` or `.cast(pl.Int64)` right after load.

Example fix

// before
s = pl.Series([date(2024,1,1), date(2024,1,2)])
s / 2  # TypeError

// after
s.cast(pl.Int64) / 2
# or unit-aware:
s.dt.epoch(time_unit='d') / 2
Defensive patterns

Strategy: type-guard

Validate before calling

if s.dtype.is_temporal() and not isinstance(s.dtype, pl.Duration):
    s = s.cast(pl.Int64)
result = s / n

Type guard

def is_dividable(s: pl.Series) -> bool:
    return not (s.dtype.is_temporal() and not isinstance(s.dtype, pl.Duration))

Try / catch

try:
    out = s / n
except TypeError as e:
    if 'datelike' not in str(e):
        raise
    out = s.cast(pl.Int64) / n

Prevention

When it happens

Trigger: Calling `/` on a Series whose dtype satisfies self.dtype.is_temporal() and is not Duration, with a non-Expr right operand: `pl.Series([...]).cast(pl.Date) / 2`, `datetime_series / 7`, `time_series / s2`. The Expr branch (other is pl.Expr) and the Duration/Decimal branches are checked before this raise.

Common situations: Developers with pandas/numpy habits try to scale timestamps or normalize dates arithmetically; code that computes fractions of epochs (e.g. 'days since 1970 / 365'); upgrading pipelines where a column silently arrives as Date/Datetime instead of the expected integer epoch.

Related errors


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