Skip to content

Commit 7b3c74d

Browse files
jbrockmendelrhshadrach
authored andcommitted
BUG: DatetimeIndex.intersection losing freq and tz (pandas-dev#33604)
1 parent cd25028 commit 7b3c74d

File tree

5 files changed

+34
-8
lines changed

5 files changed

+34
-8
lines changed

doc/source/whatsnew/v1.1.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,7 @@ Datetimelike
458458
- Bug in :class:`Timestamp` arithmetic when adding or subtracting a ``np.ndarray`` with ``timedelta64`` dtype (:issue:`33296`)
459459
- Bug in :meth:`DatetimeIndex.to_period` not infering the frequency when called with no arguments (:issue:`33358`)
460460
- Bug in :meth:`DatetimeIndex.tz_localize` incorrectly retaining ``freq`` in some cases where the original freq is no longer valid (:issue:`30511`)
461+
- Bug in :meth:`DatetimeIndex.intersection` losing ``freq`` and timezone in some cases (:issue:`33604`)
461462

462463
Timedelta
463464
^^^^^^^^^

pandas/core/indexes/datetimelike.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -724,10 +724,10 @@ def intersection(self, other, sort=False):
724724
start = right[0]
725725

726726
if end < start:
727-
return type(self)(data=[])
727+
return type(self)(data=[], dtype=self.dtype, freq=self.freq)
728728
else:
729729
lslice = slice(*left.slice_locs(start, end))
730-
left_chunk = left.values[lslice]
730+
left_chunk = left._values[lslice]
731731
return self._shallow_copy(left_chunk)
732732

733733
def _can_fast_union(self, other) -> bool:

pandas/tests/indexes/datetimes/test_indexing.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,9 @@ def test_getitem(self):
7575
def test_dti_business_getitem(self):
7676
rng = pd.bdate_range(START, END)
7777
smaller = rng[:5]
78-
exp = DatetimeIndex(rng.view(np.ndarray)[:5])
78+
exp = DatetimeIndex(rng.view(np.ndarray)[:5], freq="B")
7979
tm.assert_index_equal(smaller, exp)
80+
assert smaller.freq == exp.freq
8081

8182
assert smaller.freq == rng.freq
8283

@@ -102,8 +103,9 @@ def test_dti_business_getitem_matplotlib_hackaround(self):
102103
def test_dti_custom_getitem(self):
103104
rng = pd.bdate_range(START, END, freq="C")
104105
smaller = rng[:5]
105-
exp = DatetimeIndex(rng.view(np.ndarray)[:5])
106+
exp = DatetimeIndex(rng.view(np.ndarray)[:5], freq="C")
106107
tm.assert_index_equal(smaller, exp)
108+
assert smaller.freq == exp.freq
107109
assert smaller.freq == rng.freq
108110

109111
sliced = rng[::5]

pandas/tests/indexes/datetimes/test_setops.py

+24-2
Original file line numberDiff line numberDiff line change
@@ -269,14 +269,34 @@ def test_intersection(self, tz, sort):
269269
assert result.freq is None
270270
assert result.tz == expected.tz
271271

272-
def test_intersection_empty(self):
272+
# parametrize over both anchored and non-anchored freqs, as they
273+
# have different code paths
274+
@pytest.mark.parametrize("freq", ["T", "B"])
275+
def test_intersection_empty(self, tz_aware_fixture, freq):
273276
# empty same freq GH2129
274-
rng = date_range("6/1/2000", "6/15/2000", freq="T")
277+
tz = tz_aware_fixture
278+
rng = date_range("6/1/2000", "6/15/2000", freq=freq, tz=tz)
275279
result = rng[0:0].intersection(rng)
276280
assert len(result) == 0
281+
assert result.freq == rng.freq
277282

278283
result = rng.intersection(rng[0:0])
279284
assert len(result) == 0
285+
assert result.freq == rng.freq
286+
287+
# no overlap GH#33604
288+
result = rng[:3].intersection(rng[-3:])
289+
tm.assert_index_equal(result, rng[:0])
290+
if freq != "T":
291+
# We don't preserve freq on non-anchored offsets
292+
assert result.freq == rng.freq
293+
294+
# swapped left and right
295+
result = rng[-3:].intersection(rng[:3])
296+
tm.assert_index_equal(result, rng[:0])
297+
if freq != "T":
298+
# We don't preserve freq on non-anchored offsets
299+
assert result.freq == rng.freq
280300

281301
def test_intersection_bug_1708(self):
282302
from pandas import DateOffset
@@ -450,6 +470,7 @@ def test_intersection_bug(self):
450470
b = bdate_range("12/10/2011", "12/20/2011")
451471
result = a.intersection(b)
452472
tm.assert_index_equal(result, b)
473+
assert result.freq == b.freq
453474

454475
def test_month_range_union_tz_pytz(self, sort):
455476
from pytz import timezone
@@ -527,3 +548,4 @@ def test_intersection_bug(self):
527548
b = bdate_range("12/10/2011", "12/20/2011", freq="C")
528549
result = a.intersection(b)
529550
tm.assert_index_equal(result, b)
551+
assert result.freq == b.freq

pandas/tests/indexes/timedeltas/test_setops.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ def test_intersection_bug_1708(self):
106106
result = index_1 & index_2
107107
expected = timedelta_range("1 day 01:00:00", periods=3, freq="h")
108108
tm.assert_index_equal(result, expected)
109+
assert result.freq == expected.freq
109110

110111
def test_intersection_equal(self, sort):
111112
# GH 24471 Test intersection outcome given the sort keyword
@@ -182,7 +183,7 @@ def test_intersection(self, rng, expected, sort):
182183
TimedeltaIndex(["2 hour", "5 hour", "5 hour", "1 hour"], name="other"),
183184
TimedeltaIndex(["1 hour", "2 hour"], name=None),
184185
),
185-
# reveresed index
186+
# reversed index
186187
(
187188
TimedeltaIndex(["1 hour", "2 hour", "4 hour", "3 hour"], name="idx")[
188189
::-1
@@ -200,7 +201,7 @@ def test_intersection_non_monotonic(self, rng, expected, sort):
200201
tm.assert_index_equal(result, expected)
201202
assert result.name == expected.name
202203

203-
# if reveresed order, frequency is still the same
204+
# if reversed order, frequency is still the same
204205
if all(base == rng[::-1]) and sort is None:
205206
assert isinstance(result.freq, Hour)
206207
else:

0 commit comments

Comments
 (0)