@@ -357,6 +357,7 @@ class _BaseOffset(object):
357
357
_typ = " dateoffset"
358
358
_normalize_cache = True
359
359
_cacheable = False
360
+ _day_opt = None
360
361
361
362
def __call__ (self , other ):
362
363
return self .apply(other)
@@ -394,6 +395,11 @@ class _BaseOffset(object):
394
395
out = ' <%s ' % n_str + className + plural + self ._repr_attrs() + ' >'
395
396
return out
396
397
398
+ def _get_offset_day (self , datetime other ):
399
+ # subclass must implement `_day_opt`; calling from the base class
400
+ # will raise NotImplementedError.
401
+ return get_day_of_month(other, self ._day_opt)
402
+
397
403
398
404
class BaseOffset (_BaseOffset ):
399
405
# Here we add __rfoo__ methods that don't play well with cdef classes
@@ -468,7 +474,7 @@ cpdef datetime shift_month(datetime stamp, int months, object day_opt=None):
468
474
return stamp.replace(year = year, month = month, day = day)
469
475
470
476
471
- cdef int get_day_of_month(datetime other, day_opt) except ? - 1 :
477
+ cpdef int get_day_of_month(datetime other, day_opt) except ? - 1 :
472
478
"""
473
479
Find the day in `other`'s month that satisfies a DateOffset's onOffset
474
480
policy, as described by the `day_opt` argument.
@@ -493,10 +499,27 @@ cdef int get_day_of_month(datetime other, day_opt) except? -1:
493
499
30
494
500
495
501
"""
502
+ cdef:
503
+ int wkday, days_in_month
504
+
496
505
if day_opt == ' start' :
497
506
return 1
498
- elif day_opt == ' end' :
499
- return monthrange(other.year, other.month)[1 ]
507
+
508
+ wkday, days_in_month = monthrange(other.year, other.month)
509
+ if day_opt == ' end' :
510
+ return days_in_month
511
+ elif day_opt == ' business_start' :
512
+ # first business day of month
513
+ return get_firstbday(wkday, days_in_month)
514
+ elif day_opt == ' business_end' :
515
+ # last business day of month
516
+ return get_lastbday(wkday, days_in_month)
517
+ elif is_integer_object(day_opt):
518
+ day = min (day_opt, days_in_month)
519
+ elif day_opt is None :
520
+ # Note: unlike `shift_month`, get_day_of_month does not
521
+ # allow day_opt = None
522
+ raise NotImplementedError
500
523
else :
501
524
raise ValueError (day_opt)
502
525
0 commit comments