Skip to content

Commit 18ab444

Browse files
authored
REF: avoid using DTA/PA methods in apply_index (#34782)
1 parent 23e208f commit 18ab444

File tree

1 file changed

+29
-21
lines changed

1 file changed

+29
-21
lines changed

pandas/_libs/tslibs/offsets.pyx

+29-21
Original file line numberDiff line numberDiff line change
@@ -2507,6 +2507,8 @@ cdef class Week(SingleConstructorOffset):
25072507
else:
25082508
return self._end_apply_index(dtindex)
25092509

2510+
@cython.wraparound(False)
2511+
@cython.boundscheck(False)
25102512
def _end_apply_index(self, dtindex):
25112513
"""
25122514
Add self to the given DatetimeIndex, specialized for case where
@@ -2518,31 +2520,37 @@ cdef class Week(SingleConstructorOffset):
25182520
25192521
Returns
25202522
-------
2521-
result : DatetimeIndex
2523+
ndarray[int64_t]
25222524
"""
2523-
i8other = dtindex.asi8
2524-
off = (i8other % DAY_NANOS).view("timedelta64[ns]")
2525+
cdef:
2526+
int64_t[:] i8other = dtindex.view("i8")
2527+
Py_ssize_t i, count = len(i8other)
2528+
int64_t val
2529+
int64_t[:] out = np.empty(count, dtype="i8")
2530+
npy_datetimestruct dts
2531+
int wday, days, weeks, n = self.n
2532+
int anchor_weekday = self.weekday
25252533

2526-
base = self._period_dtype_code
2527-
base_period = dtindex.to_period(base)
2534+
with nogil:
2535+
for i in range(count):
2536+
val = i8other[i]
2537+
if val == NPY_NAT:
2538+
out[i] = NPY_NAT
2539+
continue
25282540

2529-
if self.n > 0:
2530-
# when adding, dates on end roll to next
2531-
normed = dtindex - off + Timedelta(1, "D") - Timedelta(1, "ns")
2532-
roll = np.where(
2533-
base_period.to_timestamp(how="end") == normed, self.n, self.n - 1
2534-
)
2535-
# integer-array addition on PeriodIndex is deprecated,
2536-
# so we use _addsub_int_array directly
2537-
shifted = base_period._addsub_int_array(roll, operator.add)
2538-
base = shifted.to_timestamp(how="end")
2539-
else:
2540-
# integer addition on PeriodIndex is deprecated,
2541-
# so we use _time_shift directly
2542-
roll = self.n
2543-
base = base_period._time_shift(roll).to_timestamp(how="end")
2541+
dt64_to_dtstruct(val, &dts)
2542+
wday = dayofweek(dts.year, dts.month, dts.day)
2543+
2544+
days = 0
2545+
weeks = n
2546+
if wday != anchor_weekday:
2547+
days = (anchor_weekday - wday) % 7
2548+
if weeks > 0:
2549+
weeks -= 1
2550+
2551+
out[i] = val + (7 * weeks + days) * DAY_NANOS
25442552

2545-
return base + off + Timedelta(1, "ns") - Timedelta(1, "D")
2553+
return out.base
25462554

25472555
def is_on_offset(self, dt) -> bool:
25482556
if self.normalize and not _is_normalized(dt):

0 commit comments

Comments
 (0)