pandas-dev/pandas · error · ValueError

to_pydatetime cannot be called with

Error message

to_pydatetime cannot be called with {self.dtype.pyarrow_dtype} type. Convert to pyarrow timestamp type.

What it means

Raised by ArrowExtensionArray._dt_to_pydatetime when the array dtype is a pyarrow date type (date32/date64). `to_pydatetime` must return Python datetime objects, but date-typed pyarrow scalars are `datetime.date`, not `datetime.datetime`, so pandas refuses rather than silently returning the wrong type.

Solutions

  1. Cast the column to a pyarrow timestamp first: `ser.astype('timestamp[ns][pyarrow]').dt.to_pydatetime()`.
  2. If you actually want date objects, access them via `ser.to_numpy()` / `.dropna().tolist()` instead of to_pydatetime.

Example fix

# before
date_series.dt.to_pydatetime()
# after
date_series.astype('timestamp[ns][pyarrow]').dt.to_pydatetime()
Defensive patterns

Strategy: validation

Validate before calling

import pyarrow as pa
if pa.types.is_date(ser.dtype.pyarrow_dtype):
    raise ValueError("to_pydatetime needs a timestamp; cast first")
ser.dt.to_pydatetime()

Type guard

def is_arrow_timestamp(ser) -> bool:
    import pyarrow as pa
    return pa.types.is_timestamp(getattr(ser.dtype, "pyarrow_dtype", None))

Try / catch

try:
    out = ser.dt.to_pydatetime()
except ValueError as e:
    if "to_pydatetime cannot be called" in str(e):
        out = ser.astype('timestamp[ns][pyarrow]').dt.to_pydatetime()
    else:
        raise

Prevention

When it happens

Trigger: Calling `ser.dt.to_pydatetime()` on a Series whose dtype is `date32[pyarrow]` or `date64[pyarrow]`.

Common situations: Reading a Parquet/Arrow column that was typed as a logical date and assuming `.dt.to_pydatetime()` works the same as on a timestamp column.

Related errors


AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11). Data as JSON: /api/errors/0da474184b190a9c. Report an issue: GitHub.

Appendix: source

Thrown at pandas/core/arrays/arrow/array.py:4270

        return self._round_temporally("round", freq, ambiguous, nonexistent)

    def _dt_day_name(self, locale: str | None = None) -> Self:
        if locale is None:
            locale = "C"
        result = pc.strftime(self._pa_array, format="%A", locale=locale)
        return self._from_pyarrow_array(result)

    def _dt_month_name(self, locale: str | None = None) -> Self:
        if locale is None:
            locale = "C"
        result = pc.strftime(self._pa_array, format="%B", locale=locale)
        return self._from_pyarrow_array(result)

    def _dt_to_pydatetime(self) -> Series:
        from pandas import Series

        if pa.types.is_date(self.dtype.pyarrow_dtype):
            raise ValueError(
                f"to_pydatetime cannot be called with {self.dtype.pyarrow_dtype} type. "
                "Convert to pyarrow timestamp type."
            )
        data = self._pa_array.to_pylist()
        if self._dtype.pyarrow_dtype.unit == "ns":
            data = [None if ts is None else ts.to_pydatetime(warn=False) for ts in data]
        return Series(data, dtype=object)

    def _dt_tz_localize(
        self,
        tz,
        ambiguous: TimeAmbiguous = "raise",
        nonexistent: TimeNonexistent = "raise",
    ) -> Self:
        if ambiguous != "raise":
            raise NotImplementedError(f"{ambiguous=} is not supported")
        nonexistent_pa = {
            "raise": "raise",

View on GitHub (pinned to 3b7651241d)