Skip to content

Commit f5d7213

Browse files
authored
PERF: MonthOffset.apply_index (#35195)
1 parent 2c3edaa commit f5d7213

File tree

2 files changed

+13
-20
lines changed

2 files changed

+13
-20
lines changed

pandas/_libs/tslibs/offsets.pyx

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@ cdef class BaseOffset:
558558

559559
def _get_offset_day(self, other: datetime) -> int:
560560
# subclass must implement `_day_opt`; calling from the base class
561-
# will raise NotImplementedError.
561+
# will implicitly assume day_opt = "business_end", see get_day_of_month.
562562
cdef:
563563
npy_datetimestruct dts
564564
pydate_to_dtstruct(other, &dts)
@@ -3611,7 +3611,6 @@ def shift_months(const int64_t[:] dtindex, int months, object day_opt=None):
36113611
out[i] = dtstruct_to_dt64(&dts)
36123612
elif day_opt in ["start", "end", "business_start", "business_end"]:
36133613
_shift_months(dtindex, out, count, months, day_opt)
3614-
36153614
else:
36163615
raise ValueError("day must be None, 'start', 'end', "
36173616
"'business_start', or 'business_end'")
@@ -3801,7 +3800,7 @@ def shift_month(stamp: datetime, months: int, day_opt: object=None) -> datetime:
38013800
return stamp.replace(year=year, month=month, day=day)
38023801

38033802

3804-
cdef inline int get_day_of_month(npy_datetimestruct* dts, day_opt) nogil except? -1:
3803+
cdef inline int get_day_of_month(npy_datetimestruct* dts, str day_opt) nogil:
38053804
"""
38063805
Find the day in `other`'s month that satisfies a DateOffset's is_on_offset
38073806
policy, as described by the `day_opt` argument.
@@ -3827,27 +3826,23 @@ cdef inline int get_day_of_month(npy_datetimestruct* dts, day_opt) nogil except?
38273826
>>> get_day_of_month(other, 'end')
38283827
30
38293828
3829+
Notes
3830+
-----
3831+
Caller is responsible for ensuring one of the four accepted day_opt values
3832+
is passed.
38303833
"""
3831-
cdef:
3832-
int days_in_month
38333834

38343835
if day_opt == "start":
38353836
return 1
38363837
elif day_opt == "end":
3837-
days_in_month = get_days_in_month(dts.year, dts.month)
3838-
return days_in_month
3838+
return get_days_in_month(dts.year, dts.month)
38393839
elif day_opt == "business_start":
38403840
# first business day of month
38413841
return get_firstbday(dts.year, dts.month)
3842-
elif day_opt == "business_end":
3842+
else:
3843+
# i.e. day_opt == "business_end":
38433844
# last business day of month
38443845
return get_lastbday(dts.year, dts.month)
3845-
elif day_opt is not None:
3846-
raise ValueError(day_opt)
3847-
elif day_opt is None:
3848-
# Note: unlike `shift_month`, get_day_of_month does not
3849-
# allow day_opt = None
3850-
raise NotImplementedError
38513846

38523847

38533848
cpdef int roll_convention(int other, int n, int compare) nogil:
@@ -3901,6 +3896,10 @@ def roll_qtrday(other: datetime, n: int, month: int,
39013896
cdef:
39023897
int months_since
39033898
npy_datetimestruct dts
3899+
3900+
if day_opt not in ["start", "end", "business_start", "business_end"]:
3901+
raise ValueError(day_opt)
3902+
39043903
pydate_to_dtstruct(other, &dts)
39053904

39063905
if modby == 12:

pandas/tests/tseries/offsets/test_offsets.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4310,12 +4310,6 @@ def test_all_offset_classes(self, tup):
43104310

43114311

43124312
# ---------------------------------------------------------------------
4313-
def test_get_offset_day_error():
4314-
# subclass of _BaseOffset must override _day_opt attribute, or we should
4315-
# get a NotImplementedError
4316-
4317-
with pytest.raises(NotImplementedError):
4318-
DateOffset()._get_offset_day(datetime.now())
43194313

43204314

43214315
def test_valid_default_arguments(offset_types):

0 commit comments

Comments
 (0)