diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index 0caacd81c53f5..9e6a2c0507f7f 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -762,7 +762,7 @@ cdef class Tick(SingleConstructorOffset): return Micro(self.n * 1000) if type(self) is Micro: return Nano(self.n * 1000) - raise NotImplementedError(type(self)) + raise ValueError("Could not convert to integer offset at any resolution") # -------------------------------------------------------------------- diff --git a/pandas/_libs/tslibs/resolution.pyx b/pandas/_libs/tslibs/resolution.pyx index b3fc1e32f68e8..91059638cd73a 100644 --- a/pandas/_libs/tslibs/resolution.pyx +++ b/pandas/_libs/tslibs/resolution.pyx @@ -27,16 +27,6 @@ cdef: int RESO_HR = 5 int RESO_DAY = 6 -reso_str_bump_map = { - "D": "H", - "H": "T", - "T": "S", - "S": "L", - "L": "U", - "U": "N", - "N": None, -} - _abbrev_to_attrnames = {v: k for k, v in attrname_to_abbrevs.items()} _reso_str_map = { @@ -168,19 +158,19 @@ class Resolution(Enum): return _reso_str_map[reso.value] @classmethod - def get_reso(cls, resostr: str) -> "Resolution": + def from_attrname(cls, attrname: str) -> "Resolution": """ Return resolution str against resolution code. Examples -------- - >>> Resolution.get_reso('second') + >>> Resolution.from_attrname('second') 2 - >>> Resolution.get_reso('second') == Resolution.RESO_SEC + >>> Resolution.from_attrname('second') == Resolution.RESO_SEC True """ - return cls(_str_reso_map[resostr]) + return cls(_str_reso_map[attrname]) @classmethod def get_attrname_from_abbrev(cls, freq: str) -> str: @@ -209,47 +199,7 @@ class Resolution(Enum): >>> Resolution.get_reso_from_freq('H') == Resolution.RESO_HR True """ - return cls.get_reso(cls.get_attrname_from_abbrev(freq)) - - @classmethod - def get_stride_from_decimal(cls, value: float, freq: str): - """ - Convert freq with decimal stride into a higher freq with integer stride - - Parameters - ---------- - value : float - freq : str - Frequency string - - Raises - ------ - ValueError - If the float cannot be converted to an integer at any resolution. - - Examples - -------- - >>> Resolution.get_stride_from_decimal(1.5, 'T') - (90, 'S') - - >>> Resolution.get_stride_from_decimal(1.04, 'H') - (3744, 'S') - - >>> Resolution.get_stride_from_decimal(1, 'D') - (1, 'D') - """ - if np.isclose(value % 1, 0): - return int(value), freq - else: - start_reso = cls.get_reso_from_freq(freq) - if start_reso.value == 0: - raise ValueError( - "Could not convert to integer offset at any resolution" - ) - - next_value = _reso_mult_map[start_reso.value] * value - next_name = reso_str_bump_map[freq] - return cls.get_stride_from_decimal(next_value, next_name) + return cls.from_attrname(cls.get_attrname_from_abbrev(freq)) # ---------------------------------------------------------------------- diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py index 877d19ef68558..250038726b719 100644 --- a/pandas/core/indexes/datetimes.py +++ b/pandas/core/indexes/datetimes.py @@ -525,7 +525,7 @@ def _validate_partial_date_slice(self, reso: str): if ( self.is_monotonic and reso in ["day", "hour", "minute", "second"] - and self._resolution >= libresolution.Resolution.get_reso(reso) + and self._resolution >= libresolution.Resolution.from_attrname(reso) ): # These resolution/monotonicity validations came from GH3931, # GH3452 and GH2369. diff --git a/pandas/tests/tseries/frequencies/test_freq_code.py b/pandas/tests/tseries/frequencies/test_freq_code.py index 51554854378ea..133db0c3d611b 100644 --- a/pandas/tests/tseries/frequencies/test_freq_code.py +++ b/pandas/tests/tseries/frequencies/test_freq_code.py @@ -10,6 +10,7 @@ ) from pandas._libs.tslibs.resolution import Resolution as _reso +from pandas.tseries.frequencies import to_offset import pandas.tseries.offsets as offsets @@ -116,7 +117,8 @@ def test_get_freq_roundtrip(freq): @pytest.mark.parametrize("freq", ["D", "H", "T", "S", "L", "U"]) def test_get_freq_roundtrip2(freq): - result = _attrname_to_abbrevs[_reso.get_str(_reso.get_reso_from_freq(freq))] + obj = _reso.get_reso_from_freq(freq) + result = _attrname_to_abbrevs[_reso.get_str(obj)] assert freq == result @@ -133,7 +135,9 @@ def test_get_freq_roundtrip2(freq): ) def test_resolution_bumping(args, expected): # see gh-14378 - assert _reso.get_stride_from_decimal(*args) == expected + off = to_offset(str(args[0]) + args[1]) + assert off.n == expected[0] + assert off._prefix == expected[1] @pytest.mark.parametrize( @@ -145,10 +149,10 @@ def test_resolution_bumping(args, expected): ], ) def test_cat(args): - msg = "Could not convert to integer offset at any resolution" + msg = "Invalid frequency" with pytest.raises(ValueError, match=msg): - _reso.get_stride_from_decimal(*args) + to_offset(str(args[0]) + args[1]) @pytest.mark.parametrize(