-
-
Notifications
You must be signed in to change notification settings - Fork 18.6k
REF: implement shift_bday #34761
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
REF: implement shift_bday #34761
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,7 +18,7 @@ from dateutil.easter import easter | |
|
||
import numpy as np | ||
cimport numpy as cnp | ||
from numpy cimport int64_t | ||
from numpy cimport int64_t, ndarray | ||
cnp.import_array() | ||
|
||
# TODO: formalize having _libs.properties "above" tslibs in the dependency structure | ||
|
@@ -1380,24 +1380,7 @@ cdef class BusinessDay(BusinessMixin): | |
@apply_index_wraps | ||
def apply_index(self, dtindex): | ||
i8other = dtindex.asi8 | ||
time = (i8other % DAY_NANOS).view("timedelta64[ns]") | ||
|
||
# to_period rolls forward to next BDay; track and | ||
# reduce n where it does when rolling forward | ||
asper = dtindex.to_period("B") | ||
|
||
if self.n > 0: | ||
shifted = (dtindex.to_perioddelta("B") - time).asi8 != 0 | ||
|
||
roll = np.where(shifted, self.n - 1, self.n) | ||
shifted = asper._addsub_int_array(roll, operator.add) | ||
else: | ||
# Integer addition is deprecated, so we use _time_shift directly | ||
roll = self.n | ||
shifted = asper._time_shift(roll) | ||
|
||
result = shifted.to_timestamp() + time | ||
return result | ||
return shift_bdays(i8other, self.n) | ||
|
||
def is_on_offset(self, dt) -> bool: | ||
if self.normalize and not _is_normalized(dt): | ||
|
@@ -3990,6 +3973,63 @@ def shift_months(const int64_t[:] dtindex, int months, object day_opt=None): | |
return np.asarray(out) | ||
|
||
|
||
cdef ndarray[int64_t] shift_bdays(const int64_t[:] i8other, int periods): | ||
""" | ||
Implementation of BusinessDay.apply_offset. | ||
|
||
Parameters | ||
---------- | ||
i8other : const int64_t[:] | ||
periods : int | ||
|
||
Returns | ||
------- | ||
ndarray[int64_t] | ||
""" | ||
cdef: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you doc-string args |
||
Py_ssize_t i, n = len(i8other) | ||
int64_t[:] result = np.empty(n, dtype="i8") | ||
int64_t val, res | ||
int wday, nadj, days | ||
npy_datetimestruct dts | ||
|
||
for i in range(n): | ||
val = i8other[i] | ||
if val == NPY_NAT: | ||
result[i] = NPY_NAT | ||
else: | ||
# The rest of this is effectively a copy of BusinessDay.apply | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TODO here to consolidate? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not really feasible; different types. |
||
nadj = periods | ||
weeks = nadj // 5 | ||
dt64_to_dtstruct(val, &dts) | ||
wday = dayofweek(dts.year, dts.month, dts.day) | ||
|
||
if nadj <= 0 and wday > 4: | ||
# roll forward | ||
nadj += 1 | ||
|
||
nadj -= 5 * weeks | ||
|
||
# nadj is always >= 0 at this point | ||
if nadj == 0 and wday > 4: | ||
# roll back | ||
days = 4 - wday | ||
elif wday > 4: | ||
# roll forward | ||
days = (7 - wday) + (nadj - 1) | ||
elif wday + nadj <= 4: | ||
# shift by n days without leaving the current week | ||
days = nadj | ||
else: | ||
# shift by nadj days plus 2 to get past the weekend | ||
days = nadj + 2 | ||
|
||
res = val + (7 * weeks + days) * DAY_NANOS | ||
result[i] = res | ||
|
||
return result.base | ||
|
||
|
||
def shift_month(stamp: datetime, months: int, | ||
day_opt: object=None) -> datetime: | ||
""" | ||
|
Uh oh!
There was an error while loading. Please reload this page.