pandas-dev/pandas · error · TypeError
Already tz-aware, use tz_convert to convert.
Error message
Already tz-aware, use tz_convert to convert.
What it means
Raised by DatetimeArray.tz_localize when the data is already tz-aware (`self.tz is not None`) and a non-None target tz is supplied. tz_localize attaches a tz to tz-naive data; once data is aware, switching tz is tz_convert's job. The check happens after the nonexistent-options validation.
Solutions
- Use tz_convert to change tz: `aware_obj.dt.tz_convert('US/Eastern')`.
- If you want to drop and re-attach a different tz: `aware_obj.dt.tz_localize(None).dt.tz_localize(new_tz)`.
- Guard with awareness check: `if s.dt.tz is None: s = s.dt.tz_localize(tz)`.
- To drop tz entirely: `aware_obj.dt.tz_localize(None)`.
Example fix
// before
s.dt.tz_localize('US/Eastern') # s is already tz-aware
// after
s.dt.tz_convert('US/Eastern') Defensive patterns
Strategy: validation
Validate before calling
import pandas as pd
def safe_localize(obj, tz):
if obj.dt.tz is None:
return obj.dt.tz_localize(tz)
return obj.dt.tz_convert(tz) Type guard
def is_tz_aware(obj) -> bool:
return getattr(getattr(obj, 'dtype', None), 'tz', None) is not None Try / catch
try:
out = s.dt.tz_localize(tz)
except TypeError as e:
if 'Already tz-aware' in str(e):
out = s.dt.tz_convert(tz)
else:
raise Prevention
- Make notebooks idempotent: check awareness before localizing.
- Centralize tz policy so data is localized exactly once at ingest.
When it happens
Trigger: Calling `aware_dti.tz_localize('US/Eastern')` on data that already has a tz (e.g. data loaded from a database with a tz, or previously localized). Also `aware_series.dt.tz_localize('UTC')`.
Common situations: Re-running a notebook cell that performed tz_localize — the second run hits already-aware data. Composing pipelines that localize defensively without first checking awareness. Loading Parquet/SQL that preserves tz and then unconditionally localizing.
Related errors
- Cannot convert tz-naive timestamps, use tz_localize to…
- Passed data is timezone-aware, incompatible with 'tz=None'…
- Cannot compare tz-naive and tz-aware datetime-like objects.
- Cannot compare tz-naive and tz-aware datetime-like objects
- Cannot pass both a timezone-aware dtype and tz=None
AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11).
Data as JSON: /api/errors/9ef17acd3948afeb.
Report an issue: GitHub.
Appendix: source
Thrown at pandas/core/arrays/datetimes.py:1113
0 2015-03-29 03:30:00+02:00
1 2015-03-29 03:30:00+02:00
dtype: datetime64[ns, Europe/Warsaw]
""" # noqa: E501
nonexistent_options = ("raise", "NaT", "shift_forward", "shift_backward")
if nonexistent not in nonexistent_options and not isinstance(
nonexistent, timedelta
):
raise ValueError(
"The nonexistent argument must be one of 'raise', "
"'NaT', 'shift_forward', 'shift_backward' or "
"a timedelta object"
)
if self.tz is not None:
if tz is None:
new_dates = tz_convert_from_utc(self.asi8, self.tz, reso=self._creso)
else:
raise TypeError("Already tz-aware, use tz_convert to convert.")
else:
tz = timezones.maybe_get_tz(tz)
# Convert to UTC
new_dates = tzconversion.tz_localize_to_utc(
self.asi8,
tz,
ambiguous=ambiguous,
nonexistent=nonexistent,
creso=self._creso,
)
new_dates_dt64 = new_dates.view(f"M8[{self.unit}]")
dtype = tz_to_dtype(tz, unit=self.unit)
return self._simple_new(new_dates_dt64, dtype=dtype)
# ----------------------------------------------------------------
# Conversion Methods - Vectorized analogues of Timestamp methodsView on GitHub (pinned to 3b7651241d)