pandas-dev/pandas · error · TypeError
DatetimeIndex has mixed timezones
Error message
DatetimeIndex has mixed timezones
What it means
Raised inside datetime._sequence_to_dt64/parse-related path when the values parse as datetimes but yield an object-dtype array (meaning some elements carry tz info and others do not, or they carry conflicting tz), and the caller disallowed object output (allow_object=False). The mixed-awareness result cannot be unified into a single datetime64[ns] or datetime64[ns, tz] dtype. GH#23675.
Solutions
- Normalize all source timestamps to a single tz before constructing the index: `[ts.tz_convert('UTC') if ts.tzinfo else ts.tz_localize('UTC') for ts in values]`.
- Strip tz from all of them: `[ts.tz_localize(None) if ts.tzinfo else ts for ts in values]`.
- If mixed awareness is genuinely desired, keep the column as object dtype and avoid DatetimeIndex.
- Validate at ingest: enforce a single tz policy at the data-source boundary.
Example fix
// before
dti = pd.DatetimeIndex(mixed_ts_list)
// after
normalized = [ts.tz_convert('UTC') if ts.tzinfo else ts.tz_localize('UTC') for ts in mixed_ts_list]
dti = pd.DatetimeIndex(normalized) Defensive patterns
Strategy: validation
Validate before calling
import pandas as pd
def normalize_to_single_tz(timestamps, target='UTC'):
out = []
for ts in timestamps:
ts = pd.Timestamp(ts)
if ts.tzinfo is None:
ts = ts.tz_localize(target)
else:
ts = ts.tz_convert(target)
out.append(ts)
return out Type guard
def all_same_awareness(timestamps) -> bool:
aware = [pd.Timestamp(t).tzinfo is not None for t in timestamps]
return all(aware) or not any(aware) Try / catch
try:
dti = pd.DatetimeIndex(values)
except TypeError as e:
if 'mixed timezones' in str(e):
values = normalize_to_single_tz(values)
dti = pd.DatetimeIndex(values)
else:
raise Prevention
- Enforce a single tz policy at the data-source boundary.
- Avoid mixing `pd.Timestamp.now()` (naive) with `pd.Timestamp.now(tz=...)` (aware) in the same collection.
When it happens
Trigger: Constructing `pd.DatetimeIndex([ts1_utc, ts2_naive, ts3_est])`, or calling `pd.to_datetime(...)` with mixed-aware timestamps when the caller forbids object fallback. Reading a column whose rows came from sources with different tz conventions.
Common situations: Concatenating Timestamps produced by `pd.Timestamp.now(tz=...)` and `pd.Timestamp.now()` in the same column. JSON/dict ingestion where some records include offsets and others do not. Database pulls mixing aware/naive across rows.
Related errors
- Cannot pass both a timezone-aware dtype and tz=None
- cannot supply both a tz and a dtype with a tz
- cannot supply both a tz and a timezone-naive dtype (i.e…
- data is already tz-aware
- Inferred time zone not equal to passed time zone
AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11).
Data as JSON: /api/errors/f8e4dcdcfae46166.
Report an issue: GitHub.
Appendix: source
Thrown at pandas/core/arrays/datetimes.py:2860
yearfirst=yearfirst,
creso=abbrev_to_npy_unit(out_unit),
)
if tz_parsed is not None:
# We can take a shortcut since the datetime64 numpy array
# is in UTC
return result, tz_parsed
elif result.dtype.kind == "M":
return result, tz_parsed
elif result.dtype == object:
# GH#23675 when called via `pd.to_datetime`, returning an object-dtype
# array is allowed. When called via `pd.DatetimeIndex`, we can
# only accept datetime64 dtype, so raise TypeError if object-dtype
# is returned, as that indicates the values can be recognized as
# datetimes but they have conflicting timezones/awareness
if allow_object:
return result, tz_parsed
raise TypeError("DatetimeIndex has mixed timezones")
else: # pragma: no cover
# GH#23675 this TypeError should never be hit, whereas the TypeError
# in the object-dtype branch above is reachable.
raise TypeError(result)
def maybe_convert_dtype(data, copy: bool, tz: tzinfo | None = None):
"""
Convert data based on dtype conventions, issuing
errors where appropriate.
Parameters
----------
data : np.ndarray or pd.Index
copy : bool
tz : tzinfo or None, default None
ReturnsView on GitHub (pinned to 3b7651241d)