{"record":{"id":"d760087ddc054a9f","repo":"pandas-dev/pandas","slug":"cannot-convert-tz-naive-timestamps-use-tz-localiz-d76008","errorCode":null,"errorMessage":"Cannot convert tz-naive timestamps, use tz_localize to localize","messagePattern":"Cannot convert tz-naive timestamps, use tz_localize to localize","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/datetimes.py","lineNumber":946,"sourceCode":"        ... )\n\n        >>> dti\n        DatetimeIndex(['2014-08-01 09:00:00+02:00',\n                       '2014-08-01 10:00:00+02:00',\n                       '2014-08-01 11:00:00+02:00'],\n                        dtype='datetime64[us, Europe/Berlin]', freq='h')\n\n        >>> dti.tz_convert(None)\n        DatetimeIndex(['2014-08-01 07:00:00',\n                       '2014-08-01 08:00:00',\n                       '2014-08-01 09:00:00'],\n                        dtype='datetime64[us]', freq='h')\n        \"\"\"  # noqa: E501\n        tz = timezones.maybe_get_tz(tz)\n\n        if self.tz is None:\n            # tz naive, use tz_localize\n            raise TypeError(\n                \"Cannot convert tz-naive timestamps, use tz_localize to localize\"\n            )\n\n        # No conversion since timestamps are all UTC to begin with\n        dtype = tz_to_dtype(tz, unit=self.unit)\n        return self._simple_new(self._ndarray, dtype=dtype)\n\n    @dtl.ravel_compat\n    def tz_localize(\n        self,\n        tz,\n        ambiguous: TimeAmbiguous = \"raise\",\n        nonexistent: TimeNonexistent = \"raise\",\n    ) -> Self:\n        \"\"\"\n        Localize tz-naive Datetime Array/Index to tz-aware Datetime Array/Index.\n\n        This method takes a time zone (tz) naive Datetime Array/Index object","sourceCodeStart":928,"sourceCodeEnd":964,"githubUrl":"https://github.com/pandas-dev/pandas/blob/71959b8cb9b2459c16e14b34f28b178ccfe14735/pandas/core/arrays/datetimes.py#L928-L964","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\nidx.tz_convert('US/Eastern')\n# after\nidx.tz_localize('UTC').tz_convert('US/Eastern')","handlingStrategy":"validation","validationCode":"def to_tz(idx, target):\n    if idx.tz is None:\n        return idx.tz_localize(target)\n    return idx.tz_convert(target)","typeGuard":"def is_aware(idx) -> bool:\n    return getattr(idx, 'tz', None) is not None","tryCatchPattern":"try:\n    out = idx.tz_convert('US/Eastern')\nexcept TypeError as e:\n    if 'tz-naive' in str(e):\n        out = idx.tz_localize('UTC').tz_convert('US/Eastern')\n    else:\n        raise","preventionTips":["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."],"tags":["datetime","timezone","tz-convert","pandas"],"analyzedSha":"71959b8cb9b2459c16e14b34f28b178ccfe14735","analyzedAt":"2026-08-07T01:30:20.476Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}