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 tz_localize when the data already has a tz (self.tz is not None) and a new tz is requested. tz_localize attaches a tz; once data is aware you must use tz_convert to change it, so pandas refuses to silently overwrite. TypeError.
Source
Thrown at pandas/core/arrays/datetimes.py:1115
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 71959b8cb9)
Solutions
- Switch to tz_convert: idx.tz_convert(target_tz).
- Branch on idx.tz: tz_localize when None, tz_convert otherwise.
- Drop the tz first with tz_localize(None) only if you genuinely want to re-localize wall time.
Example fix
# before
idx.tz_localize('US/Eastern') # idx already aware
# after
idx.tz_convert('US/Eastern') Defensive patterns
Strategy: validation
Validate before calling
def set_tz(idx, target):
if idx.tz is not None:
return idx.tz_convert(target)
return idx.tz_localize(target) Type guard
def is_aware(idx) -> bool:
return getattr(idx, 'tz', None) is not None Try / catch
try:
out = idx.tz_localize('UTC')
except TypeError as e:
if 'Already tz-aware' in str(e):
out = idx.tz_convert('UTC')
else:
raise Prevention
- Branch on idx.tz: localize when None, convert otherwise.
- Avoid blanket tz_localize in generic helpers.
- Track column awareness in schema metadata.
When it happens
Trigger: Calling .tz_localize('UTC') on data that was parsed with utc=True or already localized; re-localizing in a loop; applying tz_localize to a column produced by another tz_localize.
Common situations: Generic pipeline that always calls tz_localize regardless of current state; data already in UTC from the DB but code treats it as naive.
Related errors
- The nonexistent argument must be one of 'raise', 'NaT', 'shi
- Cannot compare tz-naive and tz-aware datetime-like objects.
- Cannot compare tz-naive and tz-aware datetime-like objects
- Cannot convert tz-naive timestamps, use tz_localize to local
- DatetimeIndex has mixed timezones
AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07).
Data as JSON: /api/errors/9ef17acd3948afeb.
Report an issue: GitHub.