@@ -47,6 +47,7 @@ from pandas._libs.tslibs.timezones cimport utc_pytz as UTC
4747from pandas._libs.tslibs.tzconversion cimport tz_convert_single
4848
4949from .dtypes cimport PeriodDtypeCode
50+ from .fields import get_start_end_field
5051from .timedeltas cimport delta_to_nanoseconds
5152from .timedeltas import Timedelta
5253from .timestamps cimport _Timestamp
@@ -2291,7 +2292,7 @@ cdef class SemiMonthOffset(SingleConstructorOffset):
22912292 after_day_of_month = days_from_start > delta
22922293
22932294 # determine the correct n for each date in dtindex
2294- roll = self ._get_roll(dtindex , before_day_of_month, after_day_of_month)
2295+ roll = self ._get_roll(i8other , before_day_of_month, after_day_of_month)
22952296
22962297 # isolate the time since it will be striped away one the next line
22972298 time = (i8other % DAY_NANOS).view(" timedelta64[ns]" )
@@ -2304,24 +2305,26 @@ cdef class SemiMonthOffset(SingleConstructorOffset):
23042305
23052306 shifted = asper._addsub_int_array(roll // 2 , operator.add)
23062307 dtindex = type (dti)(shifted.to_timestamp())
2308+ dt64other = np.asarray(dtindex)
23072309
23082310 # apply the correct day
2309- dtindex = self ._apply_index_days(dtindex , roll)
2311+ dt64result = self ._apply_index_days(dt64other , roll)
23102312
2311- return dtindex + time
2313+ return dt64result + time
23122314
2313- def _get_roll (self , dtindex , before_day_of_month , after_day_of_month ):
2315+ def _get_roll (self , i8other , before_day_of_month , after_day_of_month ):
23142316 """
23152317 Return an array with the correct n for each date in dtindex.
23162318
23172319 The roll array is based on the fact that dtindex gets rolled back to
23182320 the first day of the month.
23192321 """
2322+ # before_day_of_month and after_day_of_month are ndarray[bool]
23202323 raise NotImplementedError
23212324
2322- def _apply_index_days (self , dtindex , roll ):
2325+ def _apply_index_days (self , dt64other , roll ):
23232326 """
2324- Apply the correct day for each date in dtindex .
2327+ Apply the correct day for each date in dt64other .
23252328 """
23262329 raise NotImplementedError
23272330
@@ -2352,9 +2355,10 @@ cdef class SemiMonthEnd(SemiMonthOffset):
23522355 day = 31 if n % 2 else self .day_of_month
23532356 return shift_month(other, months, day)
23542357
2355- def _get_roll (self , dtindex , before_day_of_month , after_day_of_month ):
2358+ def _get_roll (self , i8other , before_day_of_month , after_day_of_month ):
2359+ # before_day_of_month and after_day_of_month are ndarray[bool]
23562360 n = self .n
2357- is_month_end = dtindex. is_month_end
2361+ is_month_end = get_start_end_field(i8other, " is_month_end" )
23582362 if n > 0 :
23592363 roll_end = np.where(is_month_end, 1 , 0 )
23602364 roll_before = np.where(before_day_of_month, n, n + 1 )
@@ -2367,22 +2371,22 @@ cdef class SemiMonthEnd(SemiMonthOffset):
23672371 roll = np.where(after_day_of_month, n + 2 , n + 1 )
23682372 return roll
23692373
2370- def _apply_index_days (self , dtindex , roll ):
2374+ def _apply_index_days (self , dt64other , roll ):
23712375 """
2372- Add days portion of offset to DatetimeIndex dtindex .
2376+ Add days portion of offset to dt64other .
23732377
23742378 Parameters
23752379 ----------
2376- dtindex : DatetimeIndex
2380+ dt64other : ndarray[datetime64[ns]]
23772381 roll : ndarray[int64_t]
23782382
23792383 Returns
23802384 -------
2381- result : DatetimeIndex
2385+ ndarray[datetime64[ns]]
23822386 """
23832387 nanos = (roll % 2 ) * Timedelta(days = self .day_of_month).value
2384- dtindex += nanos.astype(" timedelta64[ns]" )
2385- return dtindex + Timedelta(days = - 1 )
2388+ dt64other += nanos.astype(" timedelta64[ns]" )
2389+ return dt64other + Timedelta(days = - 1 )
23862390
23872391
23882392cdef class SemiMonthBegin(SemiMonthOffset):
@@ -2409,9 +2413,10 @@ cdef class SemiMonthBegin(SemiMonthOffset):
24092413 day = 1 if n % 2 else self .day_of_month
24102414 return shift_month(other, months, day)
24112415
2412- def _get_roll (self , dtindex , before_day_of_month , after_day_of_month ):
2416+ def _get_roll (self , i8other , before_day_of_month , after_day_of_month ):
2417+ # before_day_of_month and after_day_of_month are ndarray[bool]
24132418 n = self .n
2414- is_month_start = dtindex. is_month_start
2419+ is_month_start = get_start_end_field(i8other, " is_month_start" )
24152420 if n > 0 :
24162421 roll = np.where(before_day_of_month, n, n + 1 )
24172422 elif n == 0 :
@@ -2424,21 +2429,21 @@ cdef class SemiMonthBegin(SemiMonthOffset):
24242429 roll = roll_after + roll_start
24252430 return roll
24262431
2427- def _apply_index_days (self , dtindex , roll ):
2432+ def _apply_index_days (self , dt64other , roll ):
24282433 """
2429- Add days portion of offset to DatetimeIndex dtindex .
2434+ Add days portion of offset to dt64other .
24302435
24312436 Parameters
24322437 ----------
2433- dtindex : DatetimeIndex
2438+ dt64other : ndarray[datetime64[ns]]
24342439 roll : ndarray[int64_t]
24352440
24362441 Returns
24372442 -------
2438- result : DatetimeIndex
2443+ ndarray[datetime64[ns]]
24392444 """
24402445 nanos = (roll % 2 ) * Timedelta(days = self .day_of_month - 1 ).value
2441- return dtindex + nanos.astype(" timedelta64[ns]" )
2446+ return dt64other + nanos.astype(" timedelta64[ns]" )
24422447
24432448
24442449# ---------------------------------------------------------------------
0 commit comments