pandas-dev/pandas · error · ValueError
left and right must have the same time zone, got
Error message
left and right must have the same time zone, got '{left.tz}' and '{right.tz}' What it means
Raised when both left and right are DatetimeIndex but their time zones differ (compared by `str(left.tz) != str(right.tz)`). IntervalArray requires tz-aware endpoints to share one timezone so the resulting dtype is unambiguous.
Solutions
- Localise or convert both sides to the same tz: `right = right.tz_localize('UTC')` (if naive) or `right = right.tz_convert(left.tz)` (if aware).
- Strip tz from both sides if naive comparison is acceptable: `left.tz_localize(None)`, `right.tz_localize(None)`.
- Verify equality with `str(left.tz) == str(right.tz)` before constructing.
Example fix
# before
l = pd.date_range('2020', periods=2, tz='UTC')
r = pd.date_range('2020', periods=2, tz='US/Eastern')
IntervalArray.from_arrays(l, r)
# after
IntervalArray.from_arrays(l, r.tz_convert('UTC')) Defensive patterns
Strategy: validation
Validate before calling
import pandas as pd
def unify_tz(left, right, target='UTC'):
if getattr(left.dtype, 'tz', None) or getattr(right.dtype, 'tz', None):
if left.tz is None:
left = left.tz_localize(target)
if right.tz is None:
right = right.tz_localize(target)
left = left.tz_convert(target)
right = right.tz_convert(target)
return left, right Type guard
import pandas as pd
def same_timezone(left, right) -> bool:
lt = getattr(left, 'tz', None)
rt = getattr(right, 'tz', None)
return str(lt) == str(rt) Try / catch
try:
arr = IntervalArray.from_arrays(left, right)
except ValueError as e:
if 'same time zone' in str(e):
right = right.tz_convert(left.tz) if right.tz else right.tz_localize(left.tz)
arr = IntervalArray.from_arrays(left, right)
else:
raise Prevention
- Localise/convert both endpoints to a single canonical tz (e.g. UTC) at ingestion.
- Assert str(left.tz) == str(right.tz) before constructing intervals.
- Beware `.dt.tz_localize(None)` calls that strip tz on one side only.
When it happens
Trigger: left tz-aware UTC, right naive or tz-aware US/Eastern; mixing timestamps parsed with different `tz_localize`/`tz_convert` calls; one side from a tz-aware column, the other from a UTC database field.
Common situations: ETL pipelines combining sources with different timezone conventions; DST-handling refactors; one side accidentally stripped of tz via `.dt.tz_localize(None)`.
Related errors
- Cannot directly set timezone. Use tz_localize() or…
- Cannot modify read-only array
- closed keyword does not match dtype.closed
- invalid dtype
- left and right must have the same length
AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11).
Data as JSON: /api/errors/ce02c3ab5c8509a9.
Report an issue: GitHub.
Appendix: source
Thrown at pandas/core/arrays/interval.py:343
isinstance(left.dtype, CategoricalDtype)
or is_string_dtype(left.dtype)
or is_string_dtype(right.dtype)
):
# GH 19016, GH 66518: reject unsupported right-side dtypes too.
msg = (
"category, object, and string subtypes are not supported "
"for IntervalArray"
)
raise TypeError(msg)
if isinstance(left, ABCPeriodIndex):
msg = "Period dtypes are not supported, use a PeriodIndex instead"
raise ValueError(msg)
if isinstance(left, ABCDatetimeIndex) and str(left.tz) != str(right.tz):
msg = (
"left and right must have the same time zone, got "
f"'{left.tz}' and '{right.tz}'"
)
raise ValueError(msg)
elif needs_i8_conversion(left.dtype) and left.unit != right.unit:
# e.g. m8[s] vs m8[ms], try to cast to a common dtype GH#55714
left_arr, right_arr = left._data._ensure_matching_resos(right._data)
left = ensure_index(left_arr)
right = ensure_index(right_arr)
# For dt64/td64 we want DatetimeArray/TimedeltaArray instead of ndarray
left = ensure_wrapped_if_datetimelike(left)
left = extract_array(left, extract_numpy=True)
right = ensure_wrapped_if_datetimelike(right)
right = extract_array(right, extract_numpy=True)
if isinstance(left, ArrowExtensionArray) or isinstance(
right, ArrowExtensionArray
):
pass
else:
lbase = getattr(left, "_ndarray", left)View on GitHub (pinned to 3b7651241d)