timezone-aware vs naive datetime comparison error
Fixes timezone-aware vs naive datetime comparison errors. Use when comparing or subtracting datetimes raises 'can't compare offset-naive and offset-aware datetimes', in pandas or plain Python. Do not use for date parsing failures, for SQL timestamp issues, or for general timezone conversion questions.
TL;DR
You compared a timezone-aware datetime with a naive one, and Python/pandas refuses because the comparison is meaningless without knowing the offset. Fix it by making both sides the same: localize the naive side with tz_localize, or drop timezones with tz_localize(None). Pick one convention for the whole pipeline and stick to it.
TypeError: can't compare offset-naive and offset-aware datetimesUse this when
- Comparing datetimes raises the offset-naive vs offset-aware TypeError
- Subtracting two datetimes fails for the same reason
- Filtering a tz-aware pandas column with a naive timestamp
Not for
to_datetimeparse failures, separate skill- SQL timestamp/timestamptz issues
- Converting between timezones when both sides are already aware
Steps
- Check which side is which:
print(a.tzinfo, b.tzinfo)Expected output: one prints None (naive), the other prints a tzinfo (aware).
- If the naive value is actually UTC, localize it:
from zoneinfo import ZoneInfo
a = a.replace(tzinfo=ZoneInfo('UTC'))Expected output: a is now aware, comparison works.
- In pandas, localize the naive column or scalar:
df['ts'] = df['ts'].dt.tz_localize('UTC')Expected output: the column becomes datetime64 with tz, filters against aware values work.
- Or strip timezones from the aware side when tz info is noise:
df['ts'] = df['ts'].dt.tz_localize(None)Expected output: naive datetimes, comparable with other naive values. Only do this if you know the data is all one zone.
- For "now" comparisons, use the aware version:
from datetime import datetime, timezone
datetime.now(timezone.utc) > aware_valueExpected output: a valid comparison. datetime.now() without tz is naive and will raise.
Variant phrasings
pandas cannot compare tz-naive and tz-aware
Same fix via .dt.tz_localize / .dt.tz_convert. Note tz_localize adds a zone to naive data; tz_convert moves aware data between zones. Mixing them up is the next most common error.
astimezone() cannot be applied to a naive datetime
You called a conversion meant for aware datetimes on a naive one. Localize first, then convert.
daylight saving time ambiguous time error
tz_localize can raise on ambiguous DST transitions; pass ambiguous='NaT' or 'infer' to handle it explicitly.
Why it happens
A naive datetime is a wall-clock reading with no zone attached; an aware one is an absolute instant. Comparing them requires assuming a zone for the naive one, and Python refuses to guess. Pandas inherits the rule.
Edge cases
pd.Timestamp.now()is naive;pd.Timestamp.now(tz='UTC')is aware. Know which you have.- Parquet round-trips can silently drop tz info; verify dtypes after read.
tz_localizeon already-aware data raises; guard with a tzinfo check or usetz_convert.- Store timestamps in UTC everywhere and convert to local zones only at display time; this whole error class mostly disappears.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_F-xMgx6WVg5m80KC1GSIjA
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.