Skip to content

Commit 3e09d97

Browse files
jbrockmendeltm9k1
authored andcommitted
CLN: Move to_period, to_perioddelta up to EA subclasses (pandas-dev#23113)
1 parent 1ca1e01 commit 3e09d97

File tree

4 files changed

+39
-28
lines changed

4 files changed

+39
-28
lines changed

pandas/core/arrays/datetimes.py

+19
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,25 @@ def to_period(self, freq=None):
820820

821821
return PeriodArrayMixin(self.values, freq=freq)
822822

823+
def to_perioddelta(self, freq):
824+
"""
825+
Calculate TimedeltaArray of difference between index
826+
values and index converted to PeriodArray at specified
827+
freq. Used for vectorized offsets
828+
829+
Parameters
830+
----------
831+
freq: Period frequency
832+
833+
Returns
834+
-------
835+
TimedeltaArray/Index
836+
"""
837+
# TODO: consider privatizing (discussion in GH#23113)
838+
from pandas.core.arrays.timedeltas import TimedeltaArrayMixin
839+
i8delta = self.asi8 - self.to_period(freq).to_timestamp().asi8
840+
return TimedeltaArrayMixin(i8delta)
841+
823842
# -----------------------------------------------------------------
824843
# Properties - Vectorized Timestamp Properties/Methods
825844

pandas/core/indexes/datetimes.py

+3-25
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
from pandas.tseries.offsets import (
4343
CDay, prefix_mapping)
4444

45-
from pandas.core.tools.timedeltas import to_timedelta
4645
from pandas.util._decorators import Appender, cache_readonly, Substitution
4746
import pandas.core.common as com
4847
import pandas.tseries.offsets as offsets
@@ -545,13 +544,6 @@ def to_series(self, keep_tz=False, index=None, name=None):
545544

546545
return Series(values, index=index, name=name)
547546

548-
@Appender(DatetimeArrayMixin.to_period.__doc__)
549-
def to_period(self, freq=None):
550-
from pandas.core.indexes.period import PeriodIndex
551-
552-
result = DatetimeArrayMixin.to_period(self, freq=freq)
553-
return PeriodIndex(result, name=self.name)
554-
555547
def snap(self, freq='S'):
556548
"""
557549
Snap time stamps to nearest occurring frequency
@@ -623,23 +615,6 @@ def union(self, other):
623615
result.freq = to_offset(result.inferred_freq)
624616
return result
625617

626-
def to_perioddelta(self, freq):
627-
"""
628-
Calculate TimedeltaIndex of difference between index
629-
values and index converted to periodIndex at specified
630-
freq. Used for vectorized offsets
631-
632-
Parameters
633-
----------
634-
freq: Period frequency
635-
636-
Returns
637-
-------
638-
y: TimedeltaIndex
639-
"""
640-
return to_timedelta(self.asi8 - self.to_period(freq)
641-
.to_timestamp().asi8)
642-
643618
def union_many(self, others):
644619
"""
645620
A bit of a hack to accelerate unioning a collection of indexes
@@ -1168,6 +1143,9 @@ def slice_indexer(self, start=None, end=None, step=None, kind=None):
11681143
is_year_end = wrap_field_accessor(DatetimeArrayMixin.is_year_end)
11691144
is_leap_year = wrap_field_accessor(DatetimeArrayMixin.is_leap_year)
11701145

1146+
to_perioddelta = wrap_array_method(DatetimeArrayMixin.to_perioddelta,
1147+
False)
1148+
to_period = wrap_array_method(DatetimeArrayMixin.to_period, True)
11711149
normalize = wrap_array_method(DatetimeArrayMixin.normalize, True)
11721150
to_julian_date = wrap_array_method(DatetimeArrayMixin.to_julian_date,
11731151
False)

pandas/core/indexes/period.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -289,9 +289,9 @@ def __array_wrap__(self, result, context=None):
289289
"""
290290
if isinstance(context, tuple) and len(context) > 0:
291291
func = context[0]
292-
if (func is np.add):
292+
if func is np.add:
293293
pass
294-
elif (func is np.subtract):
294+
elif func is np.subtract:
295295
name = self.name
296296
left = context[1][0]
297297
right = context[1][1]
@@ -312,7 +312,7 @@ def __array_wrap__(self, result, context=None):
312312
return result
313313
# the result is object dtype array of Period
314314
# cannot pass _simple_new as it is
315-
return self._shallow_copy(result, freq=self.freq, name=self.name)
315+
return type(self)(result, freq=self.freq, name=self.name)
316316

317317
@property
318318
def size(self):

pandas/tests/arrays/test_datetimelike.py

+14
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,20 @@ def test_astype_object(self, tz_naive_fixture):
7979
assert asobj.dtype == 'O'
8080
assert list(asobj) == list(dti)
8181

82+
@pytest.mark.parametrize('freqstr', ['D', 'B', 'W', 'M', 'Q', 'Y'])
83+
def test_to_perioddelta(self, datetime_index, freqstr):
84+
# GH#23113
85+
dti = datetime_index
86+
arr = DatetimeArrayMixin(dti)
87+
88+
expected = dti.to_perioddelta(freq=freqstr)
89+
result = arr.to_perioddelta(freq=freqstr)
90+
assert isinstance(result, TimedeltaArrayMixin)
91+
92+
# placeholder until these become actual EA subclasses and we can use
93+
# an EA-specific tm.assert_ function
94+
tm.assert_index_equal(pd.Index(result), pd.Index(expected))
95+
8296
@pytest.mark.parametrize('freqstr', ['D', 'B', 'W', 'M', 'Q', 'Y'])
8397
def test_to_period(self, datetime_index, freqstr):
8498
dti = datetime_index

0 commit comments

Comments
 (0)