From 58c8c6fa42ba01a6840a4f49e7df5de7abf1e572 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Fri, 22 May 2020 14:40:18 -0700 Subject: [PATCH 1/2] REF: make MonthOffset a cdef class --- pandas/_libs/tslibs/offsets.pyx | 25 ++++++++++++++++++++ pandas/tests/tseries/offsets/conftest.py | 4 +++- pandas/tseries/offsets.py | 30 ++++++------------------ 3 files changed, 35 insertions(+), 24 deletions(-) diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index 4fd70843d2c42..dc459d9e130c1 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -1299,6 +1299,31 @@ cdef class QuarterOffset(BaseOffset): return type(dtindex)._simple_new(shifted, dtype=dtindex.dtype) +cdef class MonthOffset(BaseOffset): + def is_on_offset(self, dt) -> bool: + if self.normalize and not is_normalized(dt): + return False + return dt.day == self._get_offset_day(dt) + + @apply_wraps + def apply(self, other): + compare_day = self._get_offset_day(other) + n = roll_convention(other.day, self.n, compare_day) + return shift_month(other, n, self._day_opt) + + @apply_index_wraps + def apply_index(self, dtindex): + shifted = shift_months(dtindex.asi8, self.n, self._day_opt) + return type(dtindex)._simple_new(shifted, dtype=dtindex.dtype) + + @classmethod + def _from_name(cls, suffix=None): + # default _from_name calls cls with no args + if suffix: + raise ValueError(f"Bad freq suffix {suffix}") + return cls() + + # ---------------------------------------------------------------------- # RelativeDelta Arithmetic diff --git a/pandas/tests/tseries/offsets/conftest.py b/pandas/tests/tseries/offsets/conftest.py index 2f6868f56c073..df68c98dca43f 100644 --- a/pandas/tests/tseries/offsets/conftest.py +++ b/pandas/tests/tseries/offsets/conftest.py @@ -1,5 +1,7 @@ import pytest +from pandas._libs.tslibs.offsets import MonthOffset + import pandas.tseries.offsets as offsets @@ -15,7 +17,7 @@ def offset_types(request): params=[ getattr(offsets, o) for o in offsets.__all__ - if issubclass(getattr(offsets, o), offsets.MonthOffset) and o != "MonthOffset" + if issubclass(getattr(offsets, o), MonthOffset) and o != "MonthOffset" ] ) def month_classes(request): diff --git a/pandas/tseries/offsets.py b/pandas/tseries/offsets.py index a1193ad2092e0..83de9da6c89d3 100644 --- a/pandas/tseries/offsets.py +++ b/pandas/tseries/offsets.py @@ -820,25 +820,7 @@ def __init__( # Month-Based Offset Classes -class MonthOffset(SingleConstructorOffset): - def is_on_offset(self, dt: datetime) -> bool: - if self.normalize and not is_normalized(dt): - return False - return dt.day == self._get_offset_day(dt) - - @apply_wraps - def apply(self, other): - compare_day = self._get_offset_day(other) - n = liboffsets.roll_convention(other.day, self.n, compare_day) - return shift_month(other, n, self._day_opt) - - @apply_index_wraps - def apply_index(self, i): - shifted = liboffsets.shift_months(i.asi8, self.n, self._day_opt) - return type(i)._simple_new(shifted, dtype=i.dtype) - - -class MonthEnd(MonthOffset): +class MonthEnd(SingleConstructorMixin, liboffsets.MonthOffset): """ DateOffset of one month end. """ @@ -847,7 +829,7 @@ class MonthEnd(MonthOffset): _day_opt = "end" -class MonthBegin(MonthOffset): +class MonthBegin(SingleConstructorMixin, liboffsets.MonthOffset): """ DateOffset of one month at beginning. """ @@ -856,7 +838,7 @@ class MonthBegin(MonthOffset): _day_opt = "start" -class BusinessMonthEnd(MonthOffset): +class BusinessMonthEnd(SingleConstructorMixin, liboffsets.MonthOffset): """ DateOffset increments between business EOM dates. """ @@ -865,7 +847,7 @@ class BusinessMonthEnd(MonthOffset): _day_opt = "business_end" -class BusinessMonthBegin(MonthOffset): +class BusinessMonthBegin(SingleConstructorMixin, liboffsets.MonthOffset): """ DateOffset of one business month at beginning. """ @@ -875,7 +857,9 @@ class BusinessMonthBegin(MonthOffset): @doc(bound="bound") -class _CustomBusinessMonth(CustomMixin, BusinessMixin, MonthOffset): +class _CustomBusinessMonth( + CustomMixin, BusinessMixin, SingleConstructorMixin, liboffsets.MonthOffset +): """ DateOffset subclass representing custom business month(s). From be4edc7846167e8a51a4c4193b77f58c41621953 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Fri, 22 May 2020 15:08:25 -0700 Subject: [PATCH 2/2] DOC: remove MonthOffset --- doc/source/reference/offset_frequency.rst | 34 ----------------------- 1 file changed, 34 deletions(-) diff --git a/doc/source/reference/offset_frequency.rst b/doc/source/reference/offset_frequency.rst index 94ac3eef66077..008f06a2c4999 100644 --- a/doc/source/reference/offset_frequency.rst +++ b/doc/source/reference/offset_frequency.rst @@ -173,40 +173,6 @@ Methods CustomBusinessHour.is_on_offset CustomBusinessHour.__call__ -MonthOffset ------------ -.. autosummary:: - :toctree: api/ - - MonthOffset - -Properties -~~~~~~~~~~ -.. autosummary:: - :toctree: api/ - - MonthOffset.freqstr - MonthOffset.kwds - MonthOffset.name - MonthOffset.nanos - MonthOffset.normalize - MonthOffset.rule_code - MonthOffset.n - -Methods -~~~~~~~ -.. autosummary:: - :toctree: api/ - - MonthOffset.apply - MonthOffset.apply_index - MonthOffset.copy - MonthOffset.isAnchored - MonthOffset.onOffset - MonthOffset.is_anchored - MonthOffset.is_on_offset - MonthOffset.__call__ - MonthEnd -------- .. autosummary::