@@ -47,6 +47,7 @@ from pandas._libs.tslibs.timezones cimport utc_pytz as UTC
47
47
from pandas._libs.tslibs.tzconversion cimport tz_convert_single
48
48
49
49
from .dtypes cimport PeriodDtypeCode
50
+ from .fields import get_start_end_field
50
51
from .timedeltas cimport delta_to_nanoseconds
51
52
from .timedeltas import Timedelta
52
53
from .timestamps cimport _Timestamp
@@ -2291,7 +2292,7 @@ cdef class SemiMonthOffset(SingleConstructorOffset):
2291
2292
after_day_of_month = days_from_start > delta
2292
2293
2293
2294
# 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)
2295
2296
2296
2297
# isolate the time since it will be striped away one the next line
2297
2298
time = (i8other % DAY_NANOS).view(" timedelta64[ns]" )
@@ -2304,24 +2305,26 @@ cdef class SemiMonthOffset(SingleConstructorOffset):
2304
2305
2305
2306
shifted = asper._addsub_int_array(roll // 2 , operator.add)
2306
2307
dtindex = type (dti)(shifted.to_timestamp())
2308
+ dt64other = np.asarray(dtindex)
2307
2309
2308
2310
# apply the correct day
2309
- dtindex = self ._apply_index_days(dtindex , roll)
2311
+ dt64result = self ._apply_index_days(dt64other , roll)
2310
2312
2311
- return dtindex + time
2313
+ return dt64result + time
2312
2314
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 ):
2314
2316
"""
2315
2317
Return an array with the correct n for each date in dtindex.
2316
2318
2317
2319
The roll array is based on the fact that dtindex gets rolled back to
2318
2320
the first day of the month.
2319
2321
"""
2322
+ # before_day_of_month and after_day_of_month are ndarray[bool]
2320
2323
raise NotImplementedError
2321
2324
2322
- def _apply_index_days (self , dtindex , roll ):
2325
+ def _apply_index_days (self , dt64other , roll ):
2323
2326
"""
2324
- Apply the correct day for each date in dtindex .
2327
+ Apply the correct day for each date in dt64other .
2325
2328
"""
2326
2329
raise NotImplementedError
2327
2330
@@ -2352,9 +2355,10 @@ cdef class SemiMonthEnd(SemiMonthOffset):
2352
2355
day = 31 if n % 2 else self .day_of_month
2353
2356
return shift_month(other, months, day)
2354
2357
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]
2356
2360
n = self .n
2357
- is_month_end = dtindex. is_month_end
2361
+ is_month_end = get_start_end_field(i8other, " is_month_end" )
2358
2362
if n > 0 :
2359
2363
roll_end = np.where(is_month_end, 1 , 0 )
2360
2364
roll_before = np.where(before_day_of_month, n, n + 1 )
@@ -2367,22 +2371,22 @@ cdef class SemiMonthEnd(SemiMonthOffset):
2367
2371
roll = np.where(after_day_of_month, n + 2 , n + 1 )
2368
2372
return roll
2369
2373
2370
- def _apply_index_days (self , dtindex , roll ):
2374
+ def _apply_index_days (self , dt64other , roll ):
2371
2375
"""
2372
- Add days portion of offset to DatetimeIndex dtindex .
2376
+ Add days portion of offset to dt64other .
2373
2377
2374
2378
Parameters
2375
2379
----------
2376
- dtindex : DatetimeIndex
2380
+ dt64other : ndarray[datetime64[ns]]
2377
2381
roll : ndarray[int64_t]
2378
2382
2379
2383
Returns
2380
2384
-------
2381
- result : DatetimeIndex
2385
+ ndarray[datetime64[ns]]
2382
2386
"""
2383
2387
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 )
2386
2390
2387
2391
2388
2392
cdef class SemiMonthBegin(SemiMonthOffset):
@@ -2409,9 +2413,10 @@ cdef class SemiMonthBegin(SemiMonthOffset):
2409
2413
day = 1 if n % 2 else self .day_of_month
2410
2414
return shift_month(other, months, day)
2411
2415
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]
2413
2418
n = self .n
2414
- is_month_start = dtindex. is_month_start
2419
+ is_month_start = get_start_end_field(i8other, " is_month_start" )
2415
2420
if n > 0 :
2416
2421
roll = np.where(before_day_of_month, n, n + 1 )
2417
2422
elif n == 0 :
@@ -2424,21 +2429,21 @@ cdef class SemiMonthBegin(SemiMonthOffset):
2424
2429
roll = roll_after + roll_start
2425
2430
return roll
2426
2431
2427
- def _apply_index_days (self , dtindex , roll ):
2432
+ def _apply_index_days (self , dt64other , roll ):
2428
2433
"""
2429
- Add days portion of offset to DatetimeIndex dtindex .
2434
+ Add days portion of offset to dt64other .
2430
2435
2431
2436
Parameters
2432
2437
----------
2433
- dtindex : DatetimeIndex
2438
+ dt64other : ndarray[datetime64[ns]]
2434
2439
roll : ndarray[int64_t]
2435
2440
2436
2441
Returns
2437
2442
-------
2438
- result : DatetimeIndex
2443
+ ndarray[datetime64[ns]]
2439
2444
"""
2440
2445
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]" )
2442
2447
2443
2448
2444
2449
# ---------------------------------------------------------------------
0 commit comments