pandas-dev/pandas · error · AssertionError

Inferred time zone not equal to passed time zone

Error message

Inferred time zone not equal to passed time zone

What it means

Raised by _infer_tz_from_endpoints as a bare AssertionError when both an inferred tz (from start/end) and an explicitly passed tz are present but disagree per timezones.tz_compare. Unlike [317] (start/end disagree with each other), this fires when start/end agree but the user-supplied tz kwarg conflicts with their inferred tz. The use of AssertionError here is a minor smell — it is a control-flow exception that escapes to the user.

Source

Thrown at pandas/core/arrays/datetimes.py:3096

    Raises
    ------
    TypeError : if start and end timezones do not agree
    """
    try:
        inferred_tz = timezones.infer_tzinfo(start, end)
    except AssertionError as err:
        # infer_tzinfo raises AssertionError if passed mismatched timezones
        raise TypeError(
            "Start and end cannot both be tz-aware with different timezones"
        ) from err

    inferred_tz = timezones.maybe_get_tz(inferred_tz)
    tz = timezones.maybe_get_tz(tz)

    if tz is not None and inferred_tz is not None:
        if not timezones.tz_compare(inferred_tz, tz):
            raise AssertionError("Inferred time zone not equal to passed time zone")

    elif inferred_tz is not None:
        tz = inferred_tz

    return tz


def _maybe_normalize_endpoints(
    start: _TimestampNoneT1, end: _TimestampNoneT2, normalize: bool
) -> tuple[_TimestampNoneT1, _TimestampNoneT2]:
    if normalize:
        if start is not None:
            start = start.normalize()

        if end is not None:
            end = end.normalize()

    return start, end

View on GitHub (pinned to 3b7651241d)

Solutions

  1. Drop the tz kwarg and let endpoints' inferred tz win, then convert the result: `rng = pd.date_range(start=ts_utc, end=ts_utc2); rng = rng.tz_convert('US/Eastern')`.
  2. Strip awareness from endpoints to match a tz-naive range, then localize.
  3. Convert endpoints to the target tz before passing: `start=ts_utc.tz_convert('US/Eastern'), end=ts_utc2.tz_convert('US/Eastern'), tz='US/Eastern'`.

Example fix

// before
rng = pd.date_range(start=ts_utc, end=ts_utc2, tz='US/Eastern')

// after
rng = pd.date_range(start=ts_utc, end=ts_utc2).tz_convert('US/Eastern')
Defensive patterns

Strategy: validation

Validate before calling

import pandas as pd

def date_range_aligned(start, end, tz):
    inferred = getattr(start, 'tzinfo', None)
    if inferred is not None and tz is not None and inferred != tz:
        tz = None  # defer to endpoints, convert after
    rng = pd.date_range(start=start, end=end, tz=tz)
    if tz is None and inferred is not None:
        rng = rng.tz_convert(inferred)
    return rng

Type guard

def tz_kwarg_matches_endpoints(start, end, tz) -> bool:
    import pandas as pd
    inf = pd.core.dtypes.common.timezones.infer_tzinfo(start, end)
    if inf is None or tz is None:
        return True
    return pd.core.dtypes.common.timezones.tz_compare(inf, tz)

Try / catch

try:
    rng = pd.date_range(start=start, end=end, tz=tz)
except AssertionError as e:
    if 'Inferred time zone' in str(e):
        rng = pd.date_range(start=start, end=end).tz_convert(tz)
    else:
        raise

Prevention

When it happens

Trigger: Calling `pd.date_range(start=ts_utc, end=ts_utc2, tz='US/Eastern')` where both endpoints are UTC-aware but the tz kwarg specifies a different tz.

Common situations: Hardcoded tz kwarg with dynamic tz-aware endpoints. Refactoring that added a tz kwarg without removing awareness from endpoints. Reusing a date_range call across datasets with different conventions.

Related errors


AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11). Data as JSON: /api/errors/eba8eb7049e59c59. Report an issue: GitHub.