{"record":{"id":"eba8eb7049e59c59","repo":"pandas-dev/pandas","slug":"inferred-time-zone-not-equal-to-passed-time-zone","errorCode":null,"errorMessage":"Inferred time zone not equal to passed time zone","messagePattern":"Inferred time zone not equal to passed time zone","errorType":"exception","errorClass":"AssertionError","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/datetimes.py","lineNumber":3096,"sourceCode":"\n    Raises\n    ------\n    TypeError : if start and end timezones do not agree\n    \"\"\"\n    try:\n        inferred_tz = timezones.infer_tzinfo(start, end)\n    except AssertionError as err:\n        # infer_tzinfo raises AssertionError if passed mismatched timezones\n        raise TypeError(\n            \"Start and end cannot both be tz-aware with different timezones\"\n        ) from err\n\n    inferred_tz = timezones.maybe_get_tz(inferred_tz)\n    tz = timezones.maybe_get_tz(tz)\n\n    if tz is not None and inferred_tz is not None:\n        if not timezones.tz_compare(inferred_tz, tz):\n            raise AssertionError(\"Inferred time zone not equal to passed time zone\")\n\n    elif inferred_tz is not None:\n        tz = inferred_tz\n\n    return tz\n\n\ndef _maybe_normalize_endpoints(\n    start: _TimestampNoneT1, end: _TimestampNoneT2, normalize: bool\n) -> tuple[_TimestampNoneT1, _TimestampNoneT2]:\n    if normalize:\n        if start is not None:\n            start = start.normalize()\n\n        if end is not None:\n            end = end.normalize()\n\n    return start, end","sourceCodeStart":3078,"sourceCodeEnd":3114,"githubUrl":"https://github.com/pandas-dev/pandas/blob/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/arrays/datetimes.py#L3078-L3114","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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')`.","Strip awareness from endpoints to match a tz-naive range, then localize.","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'`."],"exampleFix":"// before\nrng = pd.date_range(start=ts_utc, end=ts_utc2, tz='US/Eastern')\n\n// after\nrng = pd.date_range(start=ts_utc, end=ts_utc2).tz_convert('US/Eastern')","handlingStrategy":"validation","validationCode":"import pandas as pd\n\ndef date_range_aligned(start, end, tz):\n    inferred = getattr(start, 'tzinfo', None)\n    if inferred is not None and tz is not None and inferred != tz:\n        tz = None  # defer to endpoints, convert after\n    rng = pd.date_range(start=start, end=end, tz=tz)\n    if tz is None and inferred is not None:\n        rng = rng.tz_convert(inferred)\n    return rng","typeGuard":"def tz_kwarg_matches_endpoints(start, end, tz) -> bool:\n    import pandas as pd\n    inf = pd.core.dtypes.common.timezones.infer_tzinfo(start, end)\n    if inf is None or tz is None:\n        return True\n    return pd.core.dtypes.common.timezones.tz_compare(inf, tz)","tryCatchPattern":"try:\n    rng = pd.date_range(start=start, end=end, tz=tz)\nexcept AssertionError as e:\n    if 'Inferred time zone' in str(e):\n        rng = pd.date_range(start=start, end=end).tz_convert(tz)\n    else:\n        raise","preventionTips":["When endpoints are tz-aware, omit the tz kwarg from date_range and convert after.","Watch for AssertionError specifically here — pandas uses it for control flow in this path."],"tags":["datetime","timezone","date-range","assertion","construction"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}