pandas-dev/pandas · error · TypeError
Cannot convert tz-naive timestamps, use tz_localize to local
Error message
Cannot convert tz-naive timestamps, use tz_localize to localize
What it means
Raised by DatetimeIndex.tz_convert when self.tz is None. tz_convert only re-interprets existing absolute (UTC) instants into another tz; it cannot invent a tz for naive data, so it points the user at tz_localize instead. TypeError.
Source
Thrown at pandas/core/arrays/datetimes.py:946
... )
>>> dti
DatetimeIndex(['2014-08-01 09:00:00+02:00',
'2014-08-01 10:00:00+02:00',
'2014-08-01 11:00:00+02:00'],
dtype='datetime64[us, Europe/Berlin]', freq='h')
>>> dti.tz_convert(None)
DatetimeIndex(['2014-08-01 07:00:00',
'2014-08-01 08:00:00',
'2014-08-01 09:00:00'],
dtype='datetime64[us]', freq='h')
""" # noqa: E501
tz = timezones.maybe_get_tz(tz)
if self.tz is None:
# tz naive, use tz_localize
raise TypeError(
"Cannot convert tz-naive timestamps, use tz_localize to localize"
)
# No conversion since timestamps are all UTC to begin with
dtype = tz_to_dtype(tz, unit=self.unit)
return self._simple_new(self._ndarray, dtype=dtype)
@dtl.ravel_compat
def tz_localize(
self,
tz,
ambiguous: TimeAmbiguous = "raise",
nonexistent: TimeNonexistent = "raise",
) -> Self:
"""
Localize tz-naive Datetime Array/Index to tz-aware Datetime Array/Index.
This method takes a time zone (tz) naive Datetime Array/Index objectView on GitHub (pinned to 71959b8cb9)
Solutions
- Use tz_localize to attach a tz first: idx.tz_localize('UTC').tz_convert('US/Eastern').
- Check idx.tz is not None before calling tz_convert; branch to tz_localize when it is None.
- At ingestion, parse with utc=True or tz_localize immediately so downstream code always sees aware data.
Example fix
# before
idx.tz_convert('US/Eastern')
# after
idx.tz_localize('UTC').tz_convert('US/Eastern') Defensive patterns
Strategy: validation
Validate before calling
def to_tz(idx, target):
if idx.tz is None:
return idx.tz_localize(target)
return idx.tz_convert(target) Type guard
def is_aware(idx) -> bool:
return getattr(idx, 'tz', None) is not None Try / catch
try:
out = idx.tz_convert('US/Eastern')
except TypeError as e:
if 'tz-naive' in str(e):
out = idx.tz_localize('UTC').tz_convert('US/Eastern')
else:
raise Prevention
- Read tz_localize as 'attach', tz_convert as 'change'.
- Always check .tz before tz_convert.
- Parse sources with utc=True to guarantee aware data downstream.
When it happens
Trigger: Calling .tz_convert('US/Eastern') on a DatetimeIndex/Series whose tz is None (created by pd.to_datetime without tz, pd.date_range without tz=, or read_csv without parse tz). Reached via Series.dt.tz_convert too.
Common situations: Confusing tz_localize (attach tz) with tz_convert (change tz); assuming pd.to_datetime already attaches UTC; calling tz_convert in a generic helper that receives mixed-awareness indexes.
Related errors
- Cannot compare tz-naive and tz-aware datetime-like objects.
- Cannot compare tz-naive and tz-aware datetime-like objects
- The nonexistent argument must be one of 'raise', 'NaT', 'shi
- Already tz-aware, use tz_convert to convert.
- DatetimeIndex has mixed timezones
AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07).
Data as JSON: /api/errors/d760087ddc054a9f.
Report an issue: GitHub.