Skip to content

Commit 17b12c2

Browse files
authored
REF: de-duplicate code in libparsing/libperiod (#38915)
1 parent fb47c75 commit 17b12c2

File tree

4 files changed

+47
-53
lines changed

4 files changed

+47
-53
lines changed

pandas/_libs/tslibs/parsing.pxd

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11

22
cpdef str get_rule_month(str source)
3+
cpdef quarter_to_myear(int year, int quarter, str freq)

pandas/_libs/tslibs/parsing.pyx

+43-16
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ cpdef bint _does_string_look_like_datetime(str py_string):
378378

379379

380380
cdef inline object _parse_dateabbr_string(object date_string, datetime default,
381-
object freq):
381+
str freq=None):
382382
cdef:
383383
object ret
384384
# year initialized to prevent compiler warnings
@@ -438,21 +438,13 @@ cdef inline object _parse_dateabbr_string(object date_string, datetime default,
438438
f'quarter must be '
439439
f'between 1 and 4: {date_string}')
440440

441-
if freq is not None:
442-
# TODO: hack attack, #1228
443-
freq = getattr(freq, "freqstr", freq)
444-
try:
445-
mnum = c_MONTH_NUMBERS[get_rule_month(freq)] + 1
446-
except (KeyError, ValueError):
447-
raise DateParseError(f'Unable to retrieve month '
448-
f'information from given '
449-
f'freq: {freq}')
450-
451-
month = (mnum + (quarter - 1) * 3) % 12 + 1
452-
if month > mnum:
453-
year -= 1
454-
else:
455-
month = (quarter - 1) * 3 + 1
441+
try:
442+
# GH#1228
443+
year, month = quarter_to_myear(year, quarter, freq)
444+
except KeyError:
445+
raise DateParseError("Unable to retrieve month "
446+
"information from given "
447+
f"freq: {freq}")
456448

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

484476

477+
cpdef quarter_to_myear(int year, int quarter, str freq):
478+
"""
479+
A quarterly frequency defines a "year" which may not coincide with
480+
the calendar-year. Find the calendar-year and calendar-month associated
481+
with the given year and quarter under the `freq`-derived calendar.
482+
483+
Parameters
484+
----------
485+
year : int
486+
quarter : int
487+
freq : str or None
488+
489+
Returns
490+
-------
491+
year : int
492+
month : int
493+
494+
See Also
495+
--------
496+
Period.qyear
497+
"""
498+
if quarter <= 0 or quarter > 4:
499+
raise ValueError("Quarter must be 1 <= q <= 4")
500+
501+
if freq is not None:
502+
mnum = c_MONTH_NUMBERS[get_rule_month(freq)] + 1
503+
month = (mnum + (quarter - 1) * 3) % 12 + 1
504+
if month > mnum:
505+
year -= 1
506+
else:
507+
month = (quarter - 1) * 3 + 1
508+
509+
return year, month
510+
511+
485512
cdef dateutil_parse(
486513
str timestr,
487514
object default,

pandas/_libs/tslibs/period.pyx

+1-36
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,7 @@ from pandas._libs.tslibs.dtypes cimport (
7474
PeriodDtypeBase,
7575
attrname_to_abbrevs,
7676
)
77-
from pandas._libs.tslibs.parsing cimport get_rule_month
78-
77+
from pandas._libs.tslibs.parsing cimport quarter_to_myear
7978
from pandas._libs.tslibs.parsing import parse_time_string
8079

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

24632462

2464-
def quarter_to_myear(year: int, quarter: int, freqstr: str):
2465-
"""
2466-
A quarterly frequency defines a "year" which may not coincide with
2467-
the calendar-year. Find the calendar-year and calendar-month associated
2468-
with the given year and quarter under the `freq`-derived calendar.
2469-
2470-
Parameters
2471-
----------
2472-
year : int
2473-
quarter : int
2474-
freqstr : str
2475-
Equivalent to freq.freqstr
2476-
2477-
Returns
2478-
-------
2479-
year : int
2480-
month : int
2481-
2482-
See Also
2483-
--------
2484-
Period.qyear
2485-
"""
2486-
if quarter <= 0 or quarter > 4:
2487-
raise ValueError('Quarter must be 1 <= q <= 4')
2488-
2489-
mnum = c_MONTH_NUMBERS[get_rule_month(freqstr)] + 1
2490-
month = (mnum + (quarter - 1) * 3) % 12 + 1
2491-
if month > mnum:
2492-
year -= 1
2493-
2494-
return year, month
2495-
# TODO: This whole func is really similar to parsing.pyx L434-L450
2496-
2497-
24982463
def validate_end_alias(how):
24992464
how_dict = {'S': 'S', 'E': 'E',
25002465
'START': 'S', 'FINISH': 'E',

pandas/core/arrays/period.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
delta_to_nanoseconds,
1313
dt64arr_to_periodarr as c_dt64arr_to_periodarr,
1414
iNaT,
15+
parsing,
1516
period as libperiod,
1617
to_offset,
1718
)
@@ -1074,7 +1075,7 @@ def _range_from_fields(
10741075
freqstr = freq.freqstr
10751076
year, quarter = _make_field_arrays(year, quarter)
10761077
for y, q in zip(year, quarter):
1077-
y, m = libperiod.quarter_to_myear(y, q, freqstr)
1078+
y, m = parsing.quarter_to_myear(y, q, freqstr)
10781079
val = libperiod.period_ordinal(y, m, 1, 1, 1, 1, 0, 0, base)
10791080
ordinals.append(val)
10801081
else:

0 commit comments

Comments
 (0)