Skip to content

Commit b59bc5d

Browse files
authored
REF: inherit BaseOffset in WeekOfMonthMixin (#34184)
1 parent b66edaa commit b59bc5d

File tree

3 files changed

+27
-25
lines changed

3 files changed

+27
-25
lines changed

pandas/_libs/tslibs/offsets.pyx

+16-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ from pandas._libs.tslibs.util cimport is_integer_object, is_datetime64_object
2323

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

26-
from pandas._libs.tslibs.ccalendar import MONTHS, DAYS
26+
from pandas._libs.tslibs.ccalendar import MONTHS, DAYS, weekday_to_int, int_to_weekday
2727
from pandas._libs.tslibs.ccalendar cimport get_days_in_month, dayofweek
2828
from pandas._libs.tslibs.conversion cimport (
2929
convert_datetime_to_tsobject,
@@ -986,10 +986,16 @@ class CustomMixin:
986986
object.__setattr__(self, "calendar", calendar)
987987

988988

989-
class WeekOfMonthMixin:
989+
class WeekOfMonthMixin(BaseOffset):
990990
"""
991991
Mixin for methods common to WeekOfMonth and LastWeekOfMonth.
992992
"""
993+
def __init__(self, n=1, normalize=False, weekday=0):
994+
BaseOffset.__init__(self, n, normalize)
995+
object.__setattr__(self, "weekday", weekday)
996+
997+
if weekday < 0 or weekday > 6:
998+
raise ValueError(f"Day must be 0<=day<=6, got {weekday}")
993999

9941000
@apply_wraps
9951001
def apply(self, other):
@@ -1010,6 +1016,14 @@ class WeekOfMonthMixin:
10101016
return False
10111017
return dt.day == self._get_offset_day(dt)
10121018

1019+
@property
1020+
def rule_code(self) -> str:
1021+
weekday = int_to_weekday.get(self.weekday, "")
1022+
if self.week == -1:
1023+
# LastWeekOfMonth
1024+
return f"{self._prefix}-{weekday}"
1025+
return f"{self._prefix}-{self.week + 1}{weekday}"
1026+
10131027

10141028
# ----------------------------------------------------------------------
10151029
# RelativeDelta Arithmetic

pandas/tseries/frequencies.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ def to_offset(freq) -> Optional[DateOffset]:
165165
)
166166
stride = int(stride)
167167
offset = _get_offset(name)
168-
offset = offset * int(np.fabs(stride) * stride_sign)
168+
offset = offset * int(np.fabs(stride) * stride_sign) # type: ignore
169169
if delta is None:
170170
delta = offset
171171
else:

pandas/tseries/offsets.py

+10-22
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ def is_on_offset(self, dt):
296296
return True
297297

298298

299-
class SingleConstructorOffset(BaseOffset):
299+
class SingleConstructorMixin:
300300
_params = cache_readonly(BaseOffset._params.fget)
301301
freqstr = cache_readonly(BaseOffset.freqstr.fget)
302302

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

310310

311+
class SingleConstructorOffset(SingleConstructorMixin, BaseOffset):
312+
pass
313+
314+
311315
class BusinessDay(BusinessMixin, SingleConstructorOffset):
312316
"""
313317
DateOffset subclass representing possibly n business days.
@@ -1308,7 +1312,7 @@ def _from_name(cls, suffix=None):
13081312
return cls(weekday=weekday)
13091313

13101314

1311-
class WeekOfMonth(liboffsets.WeekOfMonthMixin, SingleConstructorOffset):
1315+
class WeekOfMonth(SingleConstructorMixin, liboffsets.WeekOfMonthMixin):
13121316
"""
13131317
Describes monthly dates like "the Tuesday of the 2nd week of each month".
13141318
@@ -1334,12 +1338,9 @@ class WeekOfMonth(liboffsets.WeekOfMonthMixin, SingleConstructorOffset):
13341338
_attributes = frozenset(["n", "normalize", "week", "weekday"])
13351339

13361340
def __init__(self, n=1, normalize=False, week=0, weekday=0):
1337-
BaseOffset.__init__(self, n, normalize)
1338-
object.__setattr__(self, "weekday", weekday)
1341+
liboffsets.WeekOfMonthMixin.__init__(self, n, normalize, weekday)
13391342
object.__setattr__(self, "week", week)
13401343

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

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

1364-
@property
1365-
def rule_code(self) -> str:
1366-
weekday = ccalendar.int_to_weekday.get(self.weekday, "")
1367-
return f"{self._prefix}-{self.week + 1}{weekday}"
1368-
13691365
@classmethod
13701366
def _from_name(cls, suffix=None):
13711367
if not suffix:
@@ -1377,7 +1373,7 @@ def _from_name(cls, suffix=None):
13771373
return cls(week=week, weekday=weekday)
13781374

13791375

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

14031399
def __init__(self, n=1, normalize=False, weekday=0):
1404-
BaseOffset.__init__(self, n, normalize)
1405-
object.__setattr__(self, "weekday", weekday)
1400+
liboffsets.WeekOfMonthMixin.__init__(self, n, normalize, weekday)
14061401

14071402
if self.n == 0:
14081403
raise ValueError("N cannot be 0")
1409-
1410-
if self.weekday < 0 or self.weekday > 6:
1411-
raise ValueError(f"Day must be 0<=day<=6, got {self.weekday}")
1404+
object.__setattr__(self, "week", -1)
14121405

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

1432-
@property
1433-
def rule_code(self) -> str:
1434-
weekday = ccalendar.int_to_weekday.get(self.weekday, "")
1435-
return f"{self._prefix}-{weekday}"
1436-
14371425
@classmethod
14381426
def _from_name(cls, suffix=None):
14391427
if not suffix:

0 commit comments

Comments
 (0)