pandas-dev/pandas · error · NotImplementedError

ambiguous is not supported.

Error message

ambiguous is not supported.

What it means

Raised by ArrowExtensionArray._round_temporally when `ambiguous != "raise"`. The pyarrow-backed implementation of dt.ceil / dt.floor / dt.round only supports the default DST-handling behavior (raise on ambiguous times); it cannot resolve fold/ambiguous timestamps for rounding. Any other value for `ambiguous` (e.g. 'infer', True/False arrays, 'NaT') triggers NotImplementedError.

Source

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

        return self.dtype.pyarrow_dtype.unit

    def _dt_normalize(self) -> Self:
        result = pc.floor_temporal(self._pa_array, 1, "day")
        return self._from_pyarrow_array(result)

    def _dt_strftime(self, format: str) -> Self:
        result = pc.strftime(self._pa_array, format=format)
        return self._from_pyarrow_array(result)

    def _round_temporally(
        self,
        method: Literal["ceil", "floor", "round"],
        freq,
        ambiguous: TimeAmbiguous = "raise",
        nonexistent: TimeNonexistent = "raise",
    ) -> Self:
        if ambiguous != "raise":
            raise NotImplementedError("ambiguous is not supported.")
        if nonexistent != "raise":
            raise NotImplementedError("nonexistent is not supported.")
        offset = to_offset(freq)
        if offset is None:
            raise ValueError(f"Must specify a valid frequency: {freq}")
        pa_supported_unit = {
            "Y": "year",
            "YS": "year",
            "Q": "quarter",
            "QS": "quarter",
            "M": "month",
            "MS": "month",
            "W": "week",
            "D": "day",
            "h": "hour",
            "min": "minute",
            "s": "second",
            "ms": "millisecond",

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Leave ambiguous at its default 'raise' and handle the DST transition explicitly before rounding.
  2. Pre-localize to a timezone without DST (e.g. UTC) and round there, then convert back: `s.dt.tz_convert("UTC").dt.floor("h").dt.tz_convert("US/Eastern")`.
  3. Cast to datetime64[ns] for the rounding step: `s.astype("datetime64[ns, US/Eastern]").dt.floor("h", ambiguous=...)` then back to pyarrow.
  4. Drop the tz for rounding if the application tolerates it.

Example fix

# before
s = pd.Series(..., dtype="timestamp[us, tz=US/Eastern][pyarrow]")
s.dt.floor("h", ambiguous="infer")  # NotImplementedError

# after: round in UTC
out = s.dt.tz_convert("UTC").dt.floor("h").dt.tz_convert("US/Eastern")
Defensive patterns

Strategy: validation

Validate before calling

def safe_round(s, freq, method="floor", nonexistent="raise"):
    if getattr(s.dt, "tz", None) is not None:  # tz-aware
        # round in UTC to avoid ambiguous handling
        return s.dt.tz_convert("UTC").dt.__getattribute__(method)(freq, nonexistent=nonexistent).dt.tz_convert(s.dt.tz)
    return s.dt.__getattribute__(method)(freq, nonexistent=nonexistent)

Type guard

def needs_utc_rounding(s) -> bool:
    return getattr(s.dt, "tz", None) is not None

Try / catch

try:
    out = s.dt.floor(freq, ambiguous=ambiguous)
except NotImplementedError:
    out = s.dt.tz_convert("UTC").dt.floor(freq).dt.tz_convert(s.dt.tz)

Prevention

When it happens

Trigger: Calling `s.dt.floor("h", ambiguous="infer")` or `s.dt.round("h", ambiguous=array_of_bools)` on a tz-aware pyarrow timestamp Series during DST transitions. Reached through dt.ceil/floor/round on timestamp[pyarrow, tz=...].

Common situations: Timezone-aware datasets that cross DST boundaries (e.g. US/Eastern fall-back). Reusing rounding code from tz-naive or numpy-backed timestamps that silently accepted ambiguous kwargs.

Related errors


AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07). Data as JSON: /api/errors/550852324616a22a. Report an issue: GitHub.