-
-
Notifications
You must be signed in to change notification settings - Fork 18.4k
Implement roll_monthday, simplify SemiMonthOffset #18762
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
Changes from 8 commits
6100c3f
aac0832
c5bc5b2
15b7916
cb07e88
eb5e72f
ec3b24d
c6f025b
f5694de
2566bf5
0838271
a649238
425d3b4
71f138d
091acc2
365cdb8
9993a91
5d773a5
a5d9dee
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 |
---|---|---|
|
@@ -523,11 +523,9 @@ def shift_quarters(int64_t[:] dtindex, int quarters, | |
n = quarters | ||
|
||
months_since = (dts.month - q1start_month) % modby | ||
compare_month = dts.month - months_since | ||
compare_month = compare_month or 12 | ||
# compare_day is only relevant for comparison in the case | ||
# where months_since == 0. | ||
compare_day = get_firstbday(dts.year, compare_month) | ||
compare_day = get_firstbday(dts.year, dts.month) | ||
|
||
if n <= 0 and (months_since != 0 or | ||
(months_since == 0 and dts.day > compare_day)): | ||
|
@@ -556,11 +554,9 @@ def shift_quarters(int64_t[:] dtindex, int quarters, | |
n = quarters | ||
|
||
months_since = (dts.month - q1start_month) % modby | ||
compare_month = dts.month - months_since | ||
compare_month = compare_month or 12 | ||
# compare_day is only relevant for comparison in the case | ||
# where months_since == 0. | ||
compare_day = get_lastbday(dts.year, compare_month) | ||
compare_day = get_lastbday(dts.year, dts.month) | ||
|
||
if n <= 0 and (months_since != 0 or | ||
(months_since == 0 and dts.day > compare_day)): | ||
|
@@ -777,6 +773,7 @@ cpdef datetime shift_month(datetime stamp, int months, object day_opt=None): | |
return stamp.replace(year=year, month=month, day=day) | ||
|
||
|
||
# TODO: Can we declare this so it will take datetime _or_ pandas_datetimestruct | ||
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 | ||
|
@@ -827,6 +824,75 @@ cpdef int get_day_of_month(datetime other, day_opt) except? -1: | |
raise ValueError(day_opt) | ||
|
||
|
||
cpdef int roll_monthday(other, int n, compare): | ||
""" | ||
Possibly increment or decrement the number of periods to shift | ||
based on rollforward/rollbackward conventions. | ||
|
||
Parameters | ||
---------- | ||
other : datetime or Timestamp | ||
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. needs typing |
||
n : number of periods to increment, before adjusting for rolling | ||
day_opt : 'start', 'end', 'business_start', 'business_end' | ||
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. this does not match the signature |
||
The convention to use in finding the day in a given month against | ||
which to compare for rollforward/rollbackward decisions. | ||
|
||
Returns | ||
------- | ||
n : int number of periods to increment | ||
""" | ||
# Either `other` and `compare` are _both_ datetimes or they are both | ||
# integers for days in the same month. | ||
|
||
if n > 0 and other < compare: | ||
n -= 1 | ||
elif n <= 0 and other > compare: | ||
# as if rolled forward already | ||
n += 1 | ||
return n | ||
|
||
|
||
cpdef int roll_qtrday(datetime other, int n, int month, day_opt='start', | ||
int modby=3) except? -1: | ||
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. make day_opt non-optional |
||
""" | ||
Possibly increment or decrement the number of periods to shift | ||
based on rollforward/rollbackward conventions. | ||
|
||
Parameters | ||
---------- | ||
other : datetime or Timestamp | ||
n : number of periods to increment, before adjusting for rolling | ||
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. does not match the signature |
||
month : reference month giving the first month of the year | ||
day_opt : 'start', 'end', 'business_start', 'business_end' | ||
The convention to use in finding the day in a given month against | ||
which to compare for rollforward/rollbackward decisions. | ||
|
||
Returns | ||
------- | ||
n : int number of periods to increment | ||
""" | ||
# TODO: type `other` as datetime-or-pandas_datetimestruct? | ||
# TODO: Merge this with roll_yearday by setting modby=12 there? | ||
# code de-duplication versus perf hit? | ||
# TODO: with small adjustments this could be used in shift_quarters | ||
months_since = other.month % modby - month % modby | ||
|
||
if n > 0: | ||
if months_since < 0 or (months_since == 0 and | ||
other.day < get_day_of_month(other, | ||
day_opt)): | ||
# pretend to roll back if on same month but | ||
# before compare_day | ||
n -= 1 | ||
else: | ||
if (months_since > 0 or (months_since == 0 and | ||
other.day > get_day_of_month(other, | ||
day_opt))): | ||
# make sure to roll forward, so negate | ||
n += 1 | ||
return n | ||
|
||
|
||
cpdef int roll_yearday(other, n, month, day_opt='start') except? -1: | ||
""" | ||
Possibly increment or decrement the number of periods to shift | ||
|
@@ -836,6 +902,7 @@ cpdef int roll_yearday(other, n, month, day_opt='start') except? -1: | |
---------- | ||
other : datetime or Timestamp | ||
n : number of periods to increment, before adjusting for rolling | ||
month : reference month giving the first month of the year | ||
day_opt : 'start', 'end' | ||
'start': returns 1 | ||
'end': returns last day of the month | ||
|
@@ -888,7 +955,7 @@ cpdef int roll_yearday(other, n, month, day_opt='start') except? -1: | |
other.day < get_day_of_month(other, | ||
day_opt)): | ||
n -= 1 | ||
elif n <= 0: | ||
else: | ||
if other.month > month or (other.month == month and | ||
other.day > get_day_of_month(other, | ||
day_opt)): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no please don't functions should not take different types like this. have 2 functions. we specifically generate templates when we have to cover lots of dtypes (not suggesting this at all here though).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, will remove this comment and address similar things you've mentioned.