{"record":{"id":"4990abcb4084b27f","repo":"pandas-dev/pandas","slug":"cannot-compare-tz-naive-and-tz-aware-datetime-like","errorCode":null,"errorMessage":"Cannot compare tz-naive and tz-aware datetime-like objects.","messagePattern":"Cannot compare tz-naive and tz-aware datetime-like objects\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/datetimes.py","lineNumber":782,"sourceCode":"        )\n\n    # -----------------------------------------------------------------\n    # Comparison Methods\n\n    def _assert_tzawareness_compat(self, other) -> None:\n        # adapted from _Timestamp._assert_tzawareness_compat\n        other_tz = getattr(other, \"tzinfo\", None)\n        other_dtype = getattr(other, \"dtype\", None)\n\n        if isinstance(other_dtype, DatetimeTZDtype):\n            # Get tzinfo from Series dtype\n            other_tz = other.dtype.tz\n        if other is NaT:\n            # pd.NaT quacks both aware and naive\n            pass\n        elif self.tz is None:\n            if other_tz is not None:\n                raise TypeError(\n                    \"Cannot compare tz-naive and tz-aware datetime-like objects.\"\n                )\n        elif other_tz is None:\n            raise TypeError(\n                \"Cannot compare tz-naive and tz-aware datetime-like objects\"\n            )\n\n    # -----------------------------------------------------------------\n    # Arithmetic Methods\n\n    def _add_offset(self, offset: BaseOffset) -> Self:\n        assert not isinstance(offset, Tick)\n\n        # For pure-timedelta DateOffset with tz-aware data, add to UTC values\n        # directly to avoid nonexistent/ambiguous time errors from\n        # re-localizing wall-time results near DST (GH#28610).\n        if (\n            self.tz is not None","sourceCodeStart":764,"sourceCodeEnd":800,"githubUrl":"https://github.com/pandas-dev/pandas/blob/71959b8cb9b2459c16e14b34f28b178ccfe14735/pandas/core/arrays/datetimes.py#L764-L800","documentation":"Raised inside DatetimeArray._assert_tzawareness_compat when comparing a tz-naive DatetimeIndex/array (self.tz is None) against an operand that carries tzinfo (a tz-aware Timestamp, Series, or DatetimeIndex). Pandas refuses the operation because wall-time vs absolute-time comparison is ambiguous; the comparison would silently produce wrong results, so it errors hard. It is a TypeError.","triggerScenarios":"Comparisons (==, <, >, isin, merge, between) where the left side is tz-naive and the right is tz-aware, e.g. naive_dti < pd.Timestamp('2020-01-01', tz='UTC'), or a DataFrame with a naive datetime column merged against an aware one. Also reached through Series.dt operations that delegate to the array's compare path.","commonSituations":"Loading data from CSV/SQL yields tz-naive timestamps while a second source (API, database with tz) is aware; user converts one column with tz_localize but forgets the other; mixing pd.Timestamp('now') (aware) with parsed strings (naive).","solutions":["Align both sides to the same awareness: localize the naive side with tz_localize('UTC') before comparing.","If one side is truly UTC underneath, tz_localize then tz_convert it to the other side's tz.","If you want a wall-time comparison, strip the aware side via tz_localize(None) (only if you accept losing absolute-time meaning).","Audit df columns with df[col].dt.tz before any merge/join/comparison."],"exampleFix":"# before\nnaive < pd.Timestamp('2020-01-01', tz='UTC')\n# after\nnaive.tz_localize('UTC') < pd.Timestamp('2020-01-01', tz='UTC')","handlingStrategy":"validation","validationCode":"def assert_same_awareness(left, right):\n    l_tz = getattr(getattr(left, 'dtype', None), 'tz', None) or getattr(left, 'tzinfo', None)\n    r_tz = getattr(getattr(right, 'dtype', None), 'tz', None) or getattr(right, 'tzinfo', None)\n    if (l_tz is None) != (r_tz is None):\n        raise TypeError(f'awareness mismatch: left tz={l_tz}, right tz={r_tz}')","typeGuard":"def is_tz_aware(x) -> bool:\n    dt = getattr(x, 'dtype', None)\n    return getattr(dt, 'tz', None) is not None or getattr(x, 'tzinfo', None) is not None","tryCatchPattern":"try:\n    result = left < right\nexcept TypeError as e:\n    if 'tz-naive and tz-aware' in str(e):\n        # localize the naive side to the aware side's tz, then retry\n        ...\n    raise","preventionTips":["Standardize every datetime column to UTC at ingestion.","Assert .dt.tz equality before merge/join on datetime keys.","Never compare raw datetime.datetime.now() (naive) against DB timestamps."],"tags":["datetime","timezone","comparison","pandas"],"analyzedSha":"71959b8cb9b2459c16e14b34f28b178ccfe14735","analyzedAt":"2026-08-07T01:30:20.476Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}