pandas-dev/pandas · error · TypeError

Cannot use .astype to convert from timezone-aware dtype to t

Error message

Cannot use .astype to convert from timezone-aware dtype to timezone-naive dtype. Use obj.tz_localize(None) or obj.tz_convert('UTC').tz_localize(None) instead.

What it means

Raised by DatetimeArray.astype (and DatetimeIndex.astype) when you call .astype() on a timezone-aware datetime array/index and request a plain numpy 'datetime64' (tz-naive) target dtype. astype cannot silently drop timezone information because that would be a lossy, ambiguous conversion. Pandas requires you to explicitly choose how to drop the tz via tz_localize(None) (keep wall time) or tz_convert('UTC').tz_localize(None) (keep UTC instant).

Source

Thrown at pandas/core/arrays/datetimes.py:731

                res_values = astype_overflowsafe(self._ndarray, np_dtype, copy=copy)
                return type(self)._simple_new(res_values, dtype=dtype)

        elif (
            self.tz is None
            and lib.is_np_dtype(dtype, "M")
            and not is_unitless(dtype)
            and is_supported_dtype(dtype)
        ):
            # unit conversion e.g. datetime64[s]
            res_values = astype_overflowsafe(self._ndarray, dtype, copy=True)
            return type(self)._simple_new(res_values, dtype=res_values.dtype)
            # TODO: preserve freq?

        elif self.tz is not None and lib.is_np_dtype(dtype, "M"):
            # pre-2.0 behavior for DTA/DTI was
            #  values.tz_convert("UTC").tz_localize(None), which did not match
            #  the Series behavior
            raise TypeError(
                "Cannot use .astype to convert from timezone-aware dtype to "
                "timezone-naive dtype. Use obj.tz_localize(None) or "
                "obj.tz_convert('UTC').tz_localize(None) instead."
            )

        elif (
            self.tz is None
            and lib.is_np_dtype(dtype, "M")
            and dtype != self.dtype
            and is_unitless(dtype)
        ):
            raise TypeError(
                "Casting to unit-less dtype 'datetime64' is not supported. "
                "Pass e.g. 'datetime64[ns]' instead."
            )

        elif isinstance(dtype, PeriodDtype):
            return self.to_period(freq=dtype.freq)

View on GitHub (pinned to 3b7651241d)

Solutions

  1. If you want to preserve the UTC instant: `obj.tz_convert('UTC').tz_localize(None)`.
  2. If you want to keep the wall-clock values and just drop tz: `obj.tz_localize(None)`.
  3. If you wanted to change units on a tz-aware array, pass a DatetimeTZDtype target like `obj.astype('datetime64[s, US/Eastern]')` instead of a tz-naive one.
  4. For DataFrame/Series columns, operate via `.dt` accessor: `s.dt.tz_localize(None)` or `s.dt.tz_convert('UTC').dt.tz_localize(None)`.

Example fix

// before
df['ts'] = df['ts'].astype('datetime64[ns]')  # ts is tz-aware

// after
df['ts'] = df['ts'].dt.tz_convert('UTC').dt.tz_localize(None)
Defensive patterns

Strategy: validation

Validate before calling

import pandas as pd

def to_tz_naive(obj):
    if getattr(obj.dtype, 'tz', None) is not None:
        return obj.dt.tz_convert('UTC').dt.tz_localize(None)
    return obj

Type guard

def is_tz_aware(obj) -> bool:
    dt = getattr(obj, 'dtype', None)
    return getattr(dt, 'tz', None) is not None

Try / catch

try:
    out = col.astype('datetime64[ns]')
except TypeError as e:
    if 'timezone-aware dtype to timezone-naive' in str(e):
        out = col.dt.tz_convert('UTC').dt.tz_localize(None)
    else:
        raise

Prevention

When it happens

Trigger: Calling `tz_aware_dti.astype('datetime64[ns]')` or `tz_aware_series.astype('datetime64[ns]')` where the source has a DatetimeTZDtype (e.g. datetime64[ns, US/Eastern]) and the target dtype has no tz. Also triggered by `astype(np.dtype('M8[ns]'))` on a tz-aware DTA.

Common situations: Downstream code that stripped tz via astype in pandas <2.0 (the pre-2.0 behavior silently did tz_convert('UTC').tz_localize(None)); migrating to pandas 2.x without updating these calls. Passing data into libraries that dislike tz-aware columns (e.g. numpy-only ML pipelines) and reaching for astype out of habit.

Related errors


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