Skip to content

Commit 6551baa

Browse files
authored
REF: make MonthOffset a cdef class (#34324)
1 parent 2391aa4 commit 6551baa

File tree

4 files changed

+35
-58
lines changed

4 files changed

+35
-58
lines changed

doc/source/reference/offset_frequency.rst

-34
Original file line numberDiff line numberDiff line change
@@ -173,40 +173,6 @@ Methods
173173
CustomBusinessHour.is_on_offset
174174
CustomBusinessHour.__call__
175175

176-
MonthOffset
177-
-----------
178-
.. autosummary::
179-
:toctree: api/
180-
181-
MonthOffset
182-
183-
Properties
184-
~~~~~~~~~~
185-
.. autosummary::
186-
:toctree: api/
187-
188-
MonthOffset.freqstr
189-
MonthOffset.kwds
190-
MonthOffset.name
191-
MonthOffset.nanos
192-
MonthOffset.normalize
193-
MonthOffset.rule_code
194-
MonthOffset.n
195-
196-
Methods
197-
~~~~~~~
198-
.. autosummary::
199-
:toctree: api/
200-
201-
MonthOffset.apply
202-
MonthOffset.apply_index
203-
MonthOffset.copy
204-
MonthOffset.isAnchored
205-
MonthOffset.onOffset
206-
MonthOffset.is_anchored
207-
MonthOffset.is_on_offset
208-
MonthOffset.__call__
209-
210176
MonthEnd
211177
--------
212178
.. autosummary::

pandas/_libs/tslibs/offsets.pyx

+25
Original file line numberDiff line numberDiff line change
@@ -1299,6 +1299,31 @@ cdef class QuarterOffset(BaseOffset):
12991299
return type(dtindex)._simple_new(shifted, dtype=dtindex.dtype)
13001300

13011301

1302+
cdef class MonthOffset(BaseOffset):
1303+
def is_on_offset(self, dt) -> bool:
1304+
if self.normalize and not is_normalized(dt):
1305+
return False
1306+
return dt.day == self._get_offset_day(dt)
1307+
1308+
@apply_wraps
1309+
def apply(self, other):
1310+
compare_day = self._get_offset_day(other)
1311+
n = roll_convention(other.day, self.n, compare_day)
1312+
return shift_month(other, n, self._day_opt)
1313+
1314+
@apply_index_wraps
1315+
def apply_index(self, dtindex):
1316+
shifted = shift_months(dtindex.asi8, self.n, self._day_opt)
1317+
return type(dtindex)._simple_new(shifted, dtype=dtindex.dtype)
1318+
1319+
@classmethod
1320+
def _from_name(cls, suffix=None):
1321+
# default _from_name calls cls with no args
1322+
if suffix:
1323+
raise ValueError(f"Bad freq suffix {suffix}")
1324+
return cls()
1325+
1326+
13021327
# ----------------------------------------------------------------------
13031328
# RelativeDelta Arithmetic
13041329

pandas/tests/tseries/offsets/conftest.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import pytest
22

3+
from pandas._libs.tslibs.offsets import MonthOffset
4+
35
import pandas.tseries.offsets as offsets
46

57

@@ -15,7 +17,7 @@ def offset_types(request):
1517
params=[
1618
getattr(offsets, o)
1719
for o in offsets.__all__
18-
if issubclass(getattr(offsets, o), offsets.MonthOffset) and o != "MonthOffset"
20+
if issubclass(getattr(offsets, o), MonthOffset) and o != "MonthOffset"
1921
]
2022
)
2123
def month_classes(request):

pandas/tseries/offsets.py

+7-23
Original file line numberDiff line numberDiff line change
@@ -820,25 +820,7 @@ def __init__(
820820
# Month-Based Offset Classes
821821

822822

823-
class MonthOffset(SingleConstructorOffset):
824-
def is_on_offset(self, dt: datetime) -> bool:
825-
if self.normalize and not is_normalized(dt):
826-
return False
827-
return dt.day == self._get_offset_day(dt)
828-
829-
@apply_wraps
830-
def apply(self, other):
831-
compare_day = self._get_offset_day(other)
832-
n = liboffsets.roll_convention(other.day, self.n, compare_day)
833-
return shift_month(other, n, self._day_opt)
834-
835-
@apply_index_wraps
836-
def apply_index(self, i):
837-
shifted = liboffsets.shift_months(i.asi8, self.n, self._day_opt)
838-
return type(i)._simple_new(shifted, dtype=i.dtype)
839-
840-
841-
class MonthEnd(MonthOffset):
823+
class MonthEnd(SingleConstructorMixin, liboffsets.MonthOffset):
842824
"""
843825
DateOffset of one month end.
844826
"""
@@ -847,7 +829,7 @@ class MonthEnd(MonthOffset):
847829
_day_opt = "end"
848830

849831

850-
class MonthBegin(MonthOffset):
832+
class MonthBegin(SingleConstructorMixin, liboffsets.MonthOffset):
851833
"""
852834
DateOffset of one month at beginning.
853835
"""
@@ -856,7 +838,7 @@ class MonthBegin(MonthOffset):
856838
_day_opt = "start"
857839

858840

859-
class BusinessMonthEnd(MonthOffset):
841+
class BusinessMonthEnd(SingleConstructorMixin, liboffsets.MonthOffset):
860842
"""
861843
DateOffset increments between business EOM dates.
862844
"""
@@ -865,7 +847,7 @@ class BusinessMonthEnd(MonthOffset):
865847
_day_opt = "business_end"
866848

867849

868-
class BusinessMonthBegin(MonthOffset):
850+
class BusinessMonthBegin(SingleConstructorMixin, liboffsets.MonthOffset):
869851
"""
870852
DateOffset of one business month at beginning.
871853
"""
@@ -875,7 +857,9 @@ class BusinessMonthBegin(MonthOffset):
875857

876858

877859
@doc(bound="bound")
878-
class _CustomBusinessMonth(CustomMixin, BusinessMixin, MonthOffset):
860+
class _CustomBusinessMonth(
861+
CustomMixin, BusinessMixin, SingleConstructorMixin, liboffsets.MonthOffset
862+
):
879863
"""
880864
DateOffset subclass representing custom business month(s).
881865

0 commit comments

Comments
 (0)