{"record":{"id":"f8e4dcdcfae46166","repo":"pandas-dev/pandas","slug":"datetimeindex-has-mixed-timezones","errorCode":null,"errorMessage":"DatetimeIndex has mixed timezones","messagePattern":"DatetimeIndex has mixed timezones","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/datetimes.py","lineNumber":2860,"sourceCode":"        yearfirst=yearfirst,\n        creso=abbrev_to_npy_unit(out_unit),\n    )\n\n    if tz_parsed is not None:\n        # We can take a shortcut since the datetime64 numpy array\n        #  is in UTC\n        return result, tz_parsed\n    elif result.dtype.kind == \"M\":\n        return result, tz_parsed\n    elif result.dtype == object:\n        # GH#23675 when called via `pd.to_datetime`, returning an object-dtype\n        #  array is allowed.  When called via `pd.DatetimeIndex`, we can\n        #  only accept datetime64 dtype, so raise TypeError if object-dtype\n        #  is returned, as that indicates the values can be recognized as\n        #  datetimes but they have conflicting timezones/awareness\n        if allow_object:\n            return result, tz_parsed\n        raise TypeError(\"DatetimeIndex has mixed timezones\")\n    else:  # pragma: no cover\n        # GH#23675 this TypeError should never be hit, whereas the TypeError\n        #  in the object-dtype branch above is reachable.\n        raise TypeError(result)\n\n\ndef maybe_convert_dtype(data, copy: bool, tz: tzinfo | None = None):\n    \"\"\"\n    Convert data based on dtype conventions, issuing\n    errors where appropriate.\n\n    Parameters\n    ----------\n    data : np.ndarray or pd.Index\n    copy : bool\n    tz : tzinfo or None, default None\n\n    Returns","sourceCodeStart":2842,"sourceCodeEnd":2878,"githubUrl":"https://github.com/pandas-dev/pandas/blob/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/arrays/datetimes.py#L2842-L2878","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\ndti = pd.DatetimeIndex(mixed_ts_list)\n\n// after\nnormalized = [ts.tz_convert('UTC') if ts.tzinfo else ts.tz_localize('UTC') for ts in mixed_ts_list]\ndti = pd.DatetimeIndex(normalized)","handlingStrategy":"validation","validationCode":"import pandas as pd\n\ndef normalize_to_single_tz(timestamps, target='UTC'):\n    out = []\n    for ts in timestamps:\n        ts = pd.Timestamp(ts)\n        if ts.tzinfo is None:\n            ts = ts.tz_localize(target)\n        else:\n            ts = ts.tz_convert(target)\n        out.append(ts)\n    return out","typeGuard":"def all_same_awareness(timestamps) -> bool:\n    aware = [pd.Timestamp(t).tzinfo is not None for t in timestamps]\n    return all(aware) or not any(aware)","tryCatchPattern":"try:\n    dti = pd.DatetimeIndex(values)\nexcept TypeError as e:\n    if 'mixed timezones' in str(e):\n        values = normalize_to_single_tz(values)\n        dti = pd.DatetimeIndex(values)\n    else:\n        raise","preventionTips":["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."],"tags":["datetime","timezone","construction","mixed-tz","to-datetime"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}