Skip to content

REF: de-duplicate code in libparsing/libperiod #38915

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 3 commits into from
Jan 4, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pandas/_libs/tslibs/parsing.pxd
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@

cpdef str get_rule_month(str source)
cpdef quarter_to_myear(int year, int quarter, str freq)
59 changes: 43 additions & 16 deletions pandas/_libs/tslibs/parsing.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ cpdef bint _does_string_look_like_datetime(str py_string):


cdef inline object _parse_dateabbr_string(object date_string, datetime default,
object freq):
str freq=None):
cdef:
object ret
# year initialized to prevent compiler warnings
Expand Down Expand Up @@ -438,21 +438,13 @@ cdef inline object _parse_dateabbr_string(object date_string, datetime default,
f'quarter must be '
f'between 1 and 4: {date_string}')

if freq is not None:
# TODO: hack attack, #1228
freq = getattr(freq, "freqstr", freq)
try:
mnum = c_MONTH_NUMBERS[get_rule_month(freq)] + 1
except (KeyError, ValueError):
raise DateParseError(f'Unable to retrieve month '
f'information from given '
f'freq: {freq}')

month = (mnum + (quarter - 1) * 3) % 12 + 1
if month > mnum:
year -= 1
else:
month = (quarter - 1) * 3 + 1
try:
# TODO: hack attack, GH#1228
Copy link
Contributor

Choose a reason for hiding this comment

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

prob can remove the comment now :->

Copy link
Member Author

Choose a reason for hiding this comment

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

updated

year, month = quarter_to_myear(year, quarter, freq)
except KeyError:
raise DateParseError("Unable to retrieve month "
"information from given "
f"freq: {freq}")

ret = default.replace(year=year, month=month)
return ret, 'quarter'
Expand Down Expand Up @@ -482,6 +474,41 @@ cdef inline object _parse_dateabbr_string(object date_string, datetime default,
raise ValueError(f'Unable to parse {date_string}')


cpdef quarter_to_myear(int year, int quarter, str freq):
"""
A quarterly frequency defines a "year" which may not coincide with
the calendar-year. Find the calendar-year and calendar-month associated
with the given year and quarter under the `freq`-derived calendar.

Parameters
----------
year : int
quarter : int
freq : str or None

Returns
-------
year : int
month : int

See Also
--------
Period.qyear
"""
if quarter <= 0 or quarter > 4:
raise ValueError("Quarter must be 1 <= q <= 4")

if freq is not None:
mnum = c_MONTH_NUMBERS[get_rule_month(freq)] + 1
month = (mnum + (quarter - 1) * 3) % 12 + 1
if month > mnum:
year -= 1
else:
month = (quarter - 1) * 3 + 1

return year, month


cdef dateutil_parse(
str timestr,
object default,
Expand Down
37 changes: 1 addition & 36 deletions pandas/_libs/tslibs/period.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ from pandas._libs.tslibs.dtypes cimport (
PeriodDtypeBase,
attrname_to_abbrevs,
)
from pandas._libs.tslibs.parsing cimport get_rule_month

from pandas._libs.tslibs.parsing cimport quarter_to_myear
Copy link
Contributor

Choose a reason for hiding this comment

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

prob can cimport parse_time_string too

Copy link
Member Author

Choose a reason for hiding this comment

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

its not cpdef

from pandas._libs.tslibs.parsing import parse_time_string

from pandas._libs.tslibs.nattype cimport (
Expand Down Expand Up @@ -2461,40 +2460,6 @@ cdef int64_t _ordinal_from_fields(int year, int month, quarter, int day,
minute, second, 0, 0, base)


def quarter_to_myear(year: int, quarter: int, freqstr: str):
"""
A quarterly frequency defines a "year" which may not coincide with
the calendar-year. Find the calendar-year and calendar-month associated
with the given year and quarter under the `freq`-derived calendar.

Parameters
----------
year : int
quarter : int
freqstr : str
Equivalent to freq.freqstr

Returns
-------
year : int
month : int

See Also
--------
Period.qyear
"""
if quarter <= 0 or quarter > 4:
raise ValueError('Quarter must be 1 <= q <= 4')

mnum = c_MONTH_NUMBERS[get_rule_month(freqstr)] + 1
month = (mnum + (quarter - 1) * 3) % 12 + 1
if month > mnum:
year -= 1

return year, month
# TODO: This whole func is really similar to parsing.pyx L434-L450


def validate_end_alias(how):
how_dict = {'S': 'S', 'E': 'E',
'START': 'S', 'FINISH': 'E',
Expand Down
3 changes: 2 additions & 1 deletion pandas/core/arrays/period.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
delta_to_nanoseconds,
dt64arr_to_periodarr as c_dt64arr_to_periodarr,
iNaT,
parsing,
period as libperiod,
to_offset,
)
Expand Down Expand Up @@ -1074,7 +1075,7 @@ def _range_from_fields(
freqstr = freq.freqstr
year, quarter = _make_field_arrays(year, quarter)
for y, q in zip(year, quarter):
y, m = libperiod.quarter_to_myear(y, q, freqstr)
y, m = parsing.quarter_to_myear(y, q, freqstr)
val = libperiod.period_ordinal(y, m, 1, 1, 1, 1, 0, 0, base)
ordinals.append(val)
else:
Expand Down