@@ -2507,6 +2507,8 @@ cdef class Week(SingleConstructorOffset):
2507
2507
else :
2508
2508
return self ._end_apply_index(dtindex)
2509
2509
2510
+ @ cython.wraparound (False )
2511
+ @ cython.boundscheck (False )
2510
2512
def _end_apply_index (self , dtindex ):
2511
2513
"""
2512
2514
Add self to the given DatetimeIndex, specialized for case where
@@ -2518,31 +2520,37 @@ cdef class Week(SingleConstructorOffset):
2518
2520
2519
2521
Returns
2520
2522
-------
2521
- result : DatetimeIndex
2523
+ ndarray[int64_t]
2522
2524
"""
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
2525
2533
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
2528
2540
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
2544
2552
2545
- return base + off + Timedelta( 1 , " ns " ) - Timedelta( 1 , " D " )
2553
+ return out. base
2546
2554
2547
2555
def is_on_offset (self , dt ) -> bool:
2548
2556
if self.normalize and not _is_normalized(dt ):
0 commit comments