@@ -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