-
-
Notifications
You must be signed in to change notification settings - Fork 18.4k
ENH: Support for "52–53-week fiscal year" / "4–4–5 calendar" and LastWeekOfMonth DateOffset #5004
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 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 |
---|---|---|
|
@@ -95,6 +95,8 @@ def get_freq_code(freqstr): | |
code = _period_str_to_code(freqstr[0]) | ||
stride = freqstr[1] | ||
except: | ||
if com.is_integer(freqstr[1]): | ||
raise | ||
code = _period_str_to_code(freqstr[1]) | ||
stride = freqstr[0] | ||
return code, stride | ||
|
@@ -227,10 +229,10 @@ def get_period_alias(offset_str): | |
'us': 'U' | ||
} | ||
|
||
#TODO: Can this be killed? | ||
for _i, _weekday in enumerate(['MON', 'TUE', 'WED', 'THU', 'FRI']): | ||
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. just define a no argument function (add add 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. @cpcloud What do you think about moving this logic to a classmethod on the respective offsets? 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. classmethod probably ok.... by function i just meant something like def initializer():
# your init code here
initializer() 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. The idea with classmethods is to put the logic for generating all instances of a given offset with the offset itself rather than having the code in separate files 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. initializer for now |
||
for _iweek in range(4): | ||
_name = 'WOM-%d%s' % (_iweek + 1, _weekday) | ||
_offset_map[_name] = offsets.WeekOfMonth(week=_iweek, weekday=_i) | ||
_rule_aliases[_name.replace('-', '@')] = _name | ||
|
||
# Note that _rule_aliases is not 1:1 (d[BA]==d[A@DEC]), and so traversal | ||
|
@@ -301,7 +303,7 @@ def to_offset(freqstr): | |
|
||
|
||
# hack to handle WOM-1MON | ||
opattern = re.compile(r'([\-]?\d*)\s*([A-Za-z]+([\-@]\d*[A-Za-z]+)?)') | ||
opattern = re.compile(r'([\-]?\d*)\s*([A-Za-z]+([\-@][\dA-Za-z\-]+)?)') | ||
|
||
|
||
def _base_and_stride(freqstr): | ||
|
@@ -356,16 +358,16 @@ def get_offset(name): | |
else: | ||
if name in _rule_aliases: | ||
name = _rule_aliases[name] | ||
try: | ||
if name not in _offset_map: | ||
|
||
if name not in _offset_map: | ||
try: | ||
# generate and cache offset | ||
offset = _make_offset(name) | ||
_offset_map[name] = offset | ||
return _offset_map[name] | ||
except (ValueError, TypeError, KeyError): | ||
# bad prefix or suffix | ||
pass | ||
raise ValueError('Bad rule name requested: %s.' % name) | ||
except (ValueError, TypeError, KeyError): | ||
# bad prefix or suffix | ||
raise ValueError('Bad rule name requested: %s.' % name) | ||
_offset_map[name] = offset | ||
return _offset_map[name] | ||
|
||
|
||
getOffset = get_offset | ||
|
@@ -401,9 +403,6 @@ def get_legacy_offset_name(offset): | |
name = offset.name | ||
return _legacy_reverse_map.get(name, name) | ||
|
||
get_offset_name = get_offset_name | ||
|
||
|
||
def get_standard_freq(freq): | ||
""" | ||
Return the standardized frequency string | ||
|
@@ -621,8 +620,12 @@ def _period_str_to_code(freqstr): | |
try: | ||
freqstr = freqstr.upper() | ||
return _period_code_map[freqstr] | ||
except: | ||
alias = _period_alias_dict[freqstr] | ||
except KeyError: | ||
try: | ||
alias = _period_alias_dict[freqstr] | ||
except KeyError: | ||
raise ValueError("Unknown freqstr: %s" % freqstr) | ||
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. @cpcloud is it acceptable to change the exception from 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. sure ... that makes a lot more sense. a user doesn't care whether the period aliases are stored in a |
||
|
||
return _period_code_map[alias] | ||
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 catch the 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. Fixed. |
||
|
||
|
||
|
@@ -839,16 +842,21 @@ def _get_monthly_rule(self): | |
'ce': 'M', 'be': 'BM'}.get(pos_check) | ||
|
||
def _get_wom_rule(self): | ||
wdiffs = unique(np.diff(self.index.week)) | ||
if not lib.ismember(wdiffs, set([4, 5])).all(): | ||
return None | ||
# wdiffs = unique(np.diff(self.index.week)) | ||
#We also need -47, -49, -48 to catch index spanning year boundary | ||
# if not lib.ismember(wdiffs, set([4, 5, -47, -49, -48])).all(): | ||
# return None | ||
|
||
weekdays = unique(self.index.weekday) | ||
if len(weekdays) > 1: | ||
return None | ||
|
||
week_of_months = unique((self.index.day - 1) // 7) | ||
if len(week_of_months) > 1: | ||
return None | ||
|
||
# get which week | ||
week = (self.index[0].day - 1) // 7 + 1 | ||
week = week_of_months[0] + 1 | ||
wd = _weekday_rule_aliases[weekdays[0]] | ||
|
||
return 'WOM-%d%s' % (week, wd) | ||
|
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.
@cpcloud I am thinking that this should also be changed to raise ValueError rather than KeyError
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.
NM. That is already handled in _period_str_to_code