Skip to content

REF: inherit BaseOffset in WeekOfMonthMixin #34184

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions pandas/_libs/tslibs/offsets.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ from pandas._libs.tslibs.util cimport is_integer_object

from pandas._libs.tslibs.base cimport ABCTick, ABCTimestamp, is_tick_object

from pandas._libs.tslibs.ccalendar import MONTHS, DAYS
from pandas._libs.tslibs.ccalendar import MONTHS, DAYS, weekday_to_int, int_to_weekday
from pandas._libs.tslibs.ccalendar cimport get_days_in_month, dayofweek
from pandas._libs.tslibs.conversion cimport (
convert_datetime_to_tsobject,
Expand Down Expand Up @@ -922,10 +922,16 @@ class CustomMixin:
object.__setattr__(self, "calendar", calendar)


class WeekOfMonthMixin:
class WeekOfMonthMixin(BaseOffset):
"""
Mixin for methods common to WeekOfMonth and LastWeekOfMonth.
"""
def __init__(self, n=1, normalize=False, weekday=0):
BaseOffset.__init__(self, n, normalize)
object.__setattr__(self, "weekday", weekday)

if weekday < 0 or weekday > 6:
raise ValueError(f"Day must be 0<=day<=6, got {weekday}")

@apply_wraps
def apply(self, other):
Expand All @@ -946,6 +952,14 @@ class WeekOfMonthMixin:
return False
return dt.day == self._get_offset_day(dt)

@property
def rule_code(self) -> str:
weekday = int_to_weekday.get(self.weekday, "")
if self.week == -1:
# LastWeekOfMonth
return f"{self._prefix}-{weekday}"
return f"{self._prefix}-{self.week + 1}{weekday}"


# ----------------------------------------------------------------------
# RelativeDelta Arithmetic
Expand Down
2 changes: 1 addition & 1 deletion pandas/tseries/frequencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ def to_offset(freq) -> Optional[DateOffset]:
)
stride = int(stride)
offset = _get_offset(name)
offset = offset * int(np.fabs(stride) * stride_sign)
offset = offset * int(np.fabs(stride) * stride_sign) # type: ignore
if delta is None:
delta = offset
else:
Expand Down
32 changes: 10 additions & 22 deletions pandas/tseries/offsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ def is_on_offset(self, dt):
return True


class SingleConstructorOffset(BaseOffset):
class SingleConstructorMixin:
_params = cache_readonly(BaseOffset._params.fget)
freqstr = cache_readonly(BaseOffset.freqstr.fget)

Expand All @@ -308,6 +308,10 @@ def _from_name(cls, suffix=None):
return cls()


class SingleConstructorOffset(SingleConstructorMixin, BaseOffset):
pass


class BusinessDay(BusinessMixin, SingleConstructorOffset):
"""
DateOffset subclass representing possibly n business days.
Expand Down Expand Up @@ -1308,7 +1312,7 @@ def _from_name(cls, suffix=None):
return cls(weekday=weekday)


class WeekOfMonth(liboffsets.WeekOfMonthMixin, SingleConstructorOffset):
class WeekOfMonth(SingleConstructorMixin, liboffsets.WeekOfMonthMixin):
"""
Describes monthly dates like "the Tuesday of the 2nd week of each month".

Expand All @@ -1334,12 +1338,9 @@ class WeekOfMonth(liboffsets.WeekOfMonthMixin, SingleConstructorOffset):
_attributes = frozenset(["n", "normalize", "week", "weekday"])

def __init__(self, n=1, normalize=False, week=0, weekday=0):
BaseOffset.__init__(self, n, normalize)
object.__setattr__(self, "weekday", weekday)
liboffsets.WeekOfMonthMixin.__init__(self, n, normalize, weekday)
object.__setattr__(self, "week", week)

if self.weekday < 0 or self.weekday > 6:
raise ValueError(f"Day must be 0<=day<=6, got {self.weekday}")
if self.week < 0 or self.week > 3:
raise ValueError(f"Week must be 0<=week<=3, got {self.week}")

Expand All @@ -1361,11 +1362,6 @@ def _get_offset_day(self, other: datetime) -> int:
shift_days = (self.weekday - wday) % 7
return 1 + shift_days + self.week * 7

@property
def rule_code(self) -> str:
weekday = ccalendar.int_to_weekday.get(self.weekday, "")
return f"{self._prefix}-{self.week + 1}{weekday}"

@classmethod
def _from_name(cls, suffix=None):
if not suffix:
Expand All @@ -1377,7 +1373,7 @@ def _from_name(cls, suffix=None):
return cls(week=week, weekday=weekday)


class LastWeekOfMonth(liboffsets.WeekOfMonthMixin, SingleConstructorOffset):
class LastWeekOfMonth(SingleConstructorMixin, liboffsets.WeekOfMonthMixin):
"""
Describes monthly dates in last week of month like "the last Tuesday of
each month".
Expand All @@ -1401,14 +1397,11 @@ class LastWeekOfMonth(liboffsets.WeekOfMonthMixin, SingleConstructorOffset):
_attributes = frozenset(["n", "normalize", "weekday"])

def __init__(self, n=1, normalize=False, weekday=0):
BaseOffset.__init__(self, n, normalize)
object.__setattr__(self, "weekday", weekday)
liboffsets.WeekOfMonthMixin.__init__(self, n, normalize, weekday)

if self.n == 0:
raise ValueError("N cannot be 0")

if self.weekday < 0 or self.weekday > 6:
raise ValueError(f"Day must be 0<=day<=6, got {self.weekday}")
object.__setattr__(self, "week", -1)

def _get_offset_day(self, other: datetime) -> int:
"""
Expand All @@ -1429,11 +1422,6 @@ def _get_offset_day(self, other: datetime) -> int:
shift_days = (wday - self.weekday) % 7
return dim - shift_days

@property
def rule_code(self) -> str:
weekday = ccalendar.int_to_weekday.get(self.weekday, "")
return f"{self._prefix}-{weekday}"

@classmethod
def _from_name(cls, suffix=None):
if not suffix:
Expand Down