Skip to content

Follow-Up: Unify apply and onOffset implementations #18329

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 9 commits into from
Nov 19, 2017
25 changes: 22 additions & 3 deletions pandas/_libs/tslibs/offsets.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,10 @@ class _BaseOffset(object):
out = '<%s' % n_str + className + plural + self._repr_attrs() + '>'
return out

def _get_offset_day(self, datetime other):
# subclass must implement `_day_opt`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so in the Base class add a NotImplementedError for this

return get_day_of_month(other, self._day_opt)


class BaseOffset(_BaseOffset):
# Here we add __rfoo__ methods that don't play well with cdef classes
Expand Down Expand Up @@ -468,7 +472,7 @@ cpdef datetime shift_month(datetime stamp, int months, object day_opt=None):
return stamp.replace(year=year, month=month, day=day)


cdef int get_day_of_month(datetime other, day_opt) except? -1:
cpdef int get_day_of_month(datetime other, day_opt) except? -1:
"""
Find the day in `other`'s month that satisfies a DateOffset's onOffset
policy, as described by the `day_opt` argument.
Expand All @@ -493,11 +497,26 @@ cdef int get_day_of_month(datetime other, day_opt) except? -1:
30

"""
cdef:
int wkday, days_in_month

if day_opt == 'start':
return 1
elif day_opt == 'end':
return monthrange(other.year, other.month)[1]

wkday, days_in_month = monthrange(other.year, other.month)
if day_opt == 'end':
return days_in_month
elif day_opt == 'business_start':
# first business day of month
return get_firstbday(wkday, days_in_month)
elif day_opt == 'business_end':
# last business day of month
return get_lastbday(wkday, days_in_month)
elif is_integer_object(day_opt):
day = min(day_opt, days_in_month)
else:
# Note: unlike `shift_month`, get_day_of_month does not
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add a test with a sub-class of BaseOffset (e.g. a dummy class) that checks this

# allow day_opt = None
raise ValueError(day_opt)


Expand Down
Loading