diff --git a/pandas/_libs/tslibs/period.pyx b/pandas/_libs/tslibs/period.pyx index 55148041c1718..a5891a9e1c22c 100644 --- a/pandas/_libs/tslibs/period.pyx +++ b/pandas/_libs/tslibs/period.pyx @@ -79,6 +79,7 @@ from pandas._libs.tslibs.offsets cimport ( is_tick_object, is_offset_object, ) +from pandas._libs.tslibs.offsets import INVALID_FREQ_ERR_MSG from pandas._libs.tslibs.tzconversion cimport tz_convert_utc_to_tzlocal @@ -1677,7 +1678,7 @@ cdef class _Period: freq = self._maybe_convert_freq(freq) how = validate_end_alias(how) base1 = self._dtype.dtype_code - base2, _ = get_freq_code(freq) + base2 = freq_to_dtype_code(freq) # self.n can't be negative or 0 end = how == 'E' @@ -1767,10 +1768,11 @@ cdef class _Period: if freq is None: base = self._dtype.dtype_code freq = get_to_timestamp_base(base) + base = freq else: freq = self._maybe_convert_freq(freq) + base = freq._period_dtype_code - base, _ = get_freq_code(freq) val = self.asfreq(freq, how) dt64 = period_ordinal_to_dt64(val.ordinal, base) @@ -2414,8 +2416,7 @@ class Period(_Period): elif is_period_object(value): other = value - if freq is None or get_freq_code( - freq) == get_freq_code(other.freq): + if freq is None or freq._period_dtype_code == other.freq._period_dtype_code: ordinal = other.ordinal freq = other.freq else: @@ -2442,6 +2443,7 @@ class Period(_Period): except KeyError: raise ValueError(f"Invalid frequency or could not " f"infer: {reso}") + freq = to_offset(freq) elif PyDateTime_Check(value): dt = value @@ -2460,7 +2462,7 @@ class Period(_Period): raise ValueError(msg) if ordinal is None: - base, _ = get_freq_code(freq) + base = freq_to_dtype_code(freq) ordinal = period_ordinal(dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.microsecond, 0, base) @@ -2472,9 +2474,17 @@ cdef bint is_period_object(object obj): return isinstance(obj, _Period) +cpdef int freq_to_dtype_code(BaseOffset freq) except? -1: + try: + return freq._period_dtype_code + except AttributeError as err: + raise ValueError(INVALID_FREQ_ERR_MSG) from err + + cdef int64_t _ordinal_from_fields(int year, int month, quarter, int day, - int hour, int minute, int second, freq): - base, mult = get_freq_code(freq) + int hour, int minute, int second, + BaseOffset freq): + base = freq_to_dtype_code(freq) if quarter is not None: year, month = quarter_to_myear(year, quarter, freq) diff --git a/pandas/core/arrays/period.py b/pandas/core/arrays/period.py index b16a3df003512..0d866aa7eae26 100644 --- a/pandas/core/arrays/period.py +++ b/pandas/core/arrays/period.py @@ -442,10 +442,11 @@ def to_timestamp(self, freq=None, how="start"): if freq is None: base = self.freq._period_dtype_code freq = libfrequencies.get_to_timestamp_base(base) + base = freq else: freq = Period._maybe_convert_freq(freq) + base = freq._period_dtype_code - base, _ = libfrequencies.get_freq_code(freq) new_data = self.asfreq(freq, how=how) new_data = libperiod.periodarr_to_dt64arr(new_data.asi8, base) @@ -962,7 +963,8 @@ def _get_ordinal_range(start, end, periods, freq, mult=1): ) if freq is not None: - _, mult = libfrequencies.get_freq_code(freq) + freq = to_offset(freq) + mult = freq.n if start is not None: start = Period(start, freq) @@ -1024,10 +1026,11 @@ def _range_from_fields( if quarter is not None: if freq is None: - freq = "Q" + freq = to_offset("Q") base = libfrequencies.FreqGroup.FR_QTR else: - base, mult = libfrequencies.get_freq_code(freq) + freq = to_offset(freq) + base = libperiod.freq_to_dtype_code(freq) if base != libfrequencies.FreqGroup.FR_QTR: raise AssertionError("base must equal FR_QTR") @@ -1037,7 +1040,8 @@ def _range_from_fields( val = libperiod.period_ordinal(y, m, 1, 1, 1, 1, 0, 0, base) ordinals.append(val) else: - base, mult = libfrequencies.get_freq_code(freq) + freq = to_offset(freq) + base = libperiod.freq_to_dtype_code(freq) arrays = _make_field_arrays(year, month, day, hour, minute, second) for y, mth, d, h, mn, s in zip(*arrays): ordinals.append(libperiod.period_ordinal(y, mth, d, h, mn, s, 0, 0, base))