Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/source/whatsnew/v1.4.4.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Fixed regressions
- Fixed regression in :meth:`DataFrame.loc` not aligning index in some cases when setting a :class:`DataFrame` (:issue:`47578`)
- Fixed regression in :meth:`DataFrame.loc` setting a length-1 array like value to a single value in the DataFrame (:issue:`46268`)
- Fixed regression in setting ``None`` or non-string value into a ``string``-dtype Series using a mask (:issue:`47628`)
- Fixed regression in :meth:`DatetimeIndex.intersection` when the :class:`DatetimeIndex` has dates crossing daylight savings time (:issue:`46702`)
- Fixed regression in :func:`merge` throwing an error when passing a :class:`Series` with a multi-level name (:issue:`47946`)
- Fixed regression in :meth:`DataFrame.eval` creating a copy when updating inplace (:issue:`47449`)
-
Expand Down
2 changes: 1 addition & 1 deletion pandas/_libs/tslibs/timezones.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ cpdef object get_timezone(tzinfo tz)
cpdef tzinfo maybe_get_tz(object tz)

cdef timedelta get_utcoffset(tzinfo tz, datetime obj)
cdef bint is_fixed_offset(tzinfo tz)
cpdef bint is_fixed_offset(tzinfo tz)

cdef object get_dst_info(tzinfo tz)
1 change: 1 addition & 0 deletions pandas/_libs/tslibs/timezones.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ def infer_tzinfo(
def maybe_get_tz(tz: str | int | np.int64 | tzinfo | None) -> tzinfo | None: ...
def get_timezone(tz: tzinfo) -> tzinfo | str: ...
def is_utc(tz: tzinfo | None) -> bool: ...
def is_fixed_offset(tz: tzinfo) -> bool: ...
2 changes: 1 addition & 1 deletion pandas/_libs/tslibs/timezones.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ cdef timedelta get_utcoffset(tzinfo tz, datetime obj):
return tz.utcoffset(obj)


cdef inline bint is_fixed_offset(tzinfo tz):
cpdef inline bint is_fixed_offset(tzinfo tz):
if treat_tz_as_dateutil(tz):
if len(tz._trans_idx) == 0 and len(tz._trans_list) == 0:
return 1
Expand Down
17 changes: 17 additions & 0 deletions pandas/core/indexes/datetimes.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,23 @@ def _formatter_func(self):
# --------------------------------------------------------------------
# Set Operation Methods

def _can_range_setop(self, other) -> bool:
# GH 46702: If self or other have non-UTC tzs, DST transitions prevent
# range representation due to no singular step
if (
self.tz is not None
and not timezones.is_utc(self.tz)
and not timezones.is_fixed_offset(self.tz)
):
return False
if (
other.tz is not None
and not timezones.is_utc(other.tz)
and not timezones.is_fixed_offset(other.tz)
):
return False
return super()._can_range_setop(other)

def union_many(self, others):
"""
A bit of a hack to accelerate unioning a collection of indexes.
Expand Down
12 changes: 12 additions & 0 deletions pandas/tests/indexes/datetimes/test_setops.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import numpy as np
import pytest
import pytz

import pandas.util._test_decorators as td

Expand Down Expand Up @@ -593,3 +594,14 @@ def test_intersection_bug(self):
result = a.intersection(b)
tm.assert_index_equal(result, b)
assert result.freq == b.freq

@pytest.mark.parametrize(
"tz", [None, "UTC", "Europe/Berlin", pytz.FixedOffset(-60)]
)
def test_intersection_dst_transition(self, tz):
# GH 46702: Europe/Berlin has DST transition
idx1 = date_range("2020-03-27", periods=5, freq="D", tz=tz)
idx2 = date_range("2020-03-30", periods=5, freq="D", tz=tz)
result = idx1.intersection(idx2)
expected = date_range("2020-03-30", periods=2, freq="D", tz=tz)
tm.assert_index_equal(result, expected)