Skip to content

Commit 9a5da9b

Browse files
authored
REF: share _get_string_slice (#42149)
1 parent 017d70c commit 9a5da9b

File tree

5 files changed

+34
-26
lines changed

5 files changed

+34
-26
lines changed

pandas/_libs/tslibs/parsing.pyx

+1-2
Original file line numberDiff line numberDiff line change
@@ -470,8 +470,7 @@ cdef inline object _parse_dateabbr_string(object date_string, datetime default,
470470
except ValueError:
471471
pass
472472

473-
if date_len == 6 and (freq == 'M' or
474-
getattr(freq, 'rule_code', None) == 'M'):
473+
if date_len == 6 and freq == 'M':
475474
year = int(date_string[:4])
476475
month = int(date_string[4:6])
477476
try:

pandas/core/indexes/datetimelike.py

+15-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
NaTType,
2727
Resolution,
2828
Tick,
29+
parsing,
2930
)
3031
from pandas._typing import (
3132
Callable,
@@ -399,9 +400,22 @@ def _summary(self, name=None) -> str:
399400
def _validate_partial_date_slice(self, reso: Resolution):
400401
raise NotImplementedError
401402

402-
def _parsed_string_to_bounds(self, reso: Resolution, parsed: datetime):
403+
def _parsed_string_to_bounds(self, reso: Resolution, parsed):
403404
raise NotImplementedError
404405

406+
def _parse_with_reso(self, label: str):
407+
# overridden by TimedeltaIndex
408+
parsed, reso_str = parsing.parse_time_string(label, self.freq)
409+
reso = Resolution.from_attrname(reso_str)
410+
return parsed, reso
411+
412+
def _get_string_slice(self, key: str):
413+
parsed, reso = self._parse_with_reso(key)
414+
try:
415+
return self._partial_date_slice(reso, parsed)
416+
except KeyError as err:
417+
raise KeyError(key) from err
418+
405419
@final
406420
def _partial_date_slice(
407421
self,

pandas/core/indexes/datetimes.py

+1-9
Original file line numberDiff line numberDiff line change
@@ -726,13 +726,11 @@ def _maybe_cast_slice_bound(self, label, side: str, kind=lib.no_default):
726726
self._deprecated_arg(kind, "kind", "_maybe_cast_slice_bound")
727727

728728
if isinstance(label, str):
729-
freq = getattr(self, "freqstr", getattr(self, "inferred_freq", None))
730729
try:
731-
parsed, reso_str = parsing.parse_time_string(label, freq)
730+
parsed, reso = self._parse_with_reso(label)
732731
except parsing.DateParseError as err:
733732
raise self._invalid_indexer("slice", label) from err
734733

735-
reso = Resolution.from_attrname(reso_str)
736734
lower, upper = self._parsed_string_to_bounds(reso, parsed)
737735
# lower, upper form the half-open interval:
738736
# [parsed, parsed + 1 freq)
@@ -750,12 +748,6 @@ def _maybe_cast_slice_bound(self, label, side: str, kind=lib.no_default):
750748

751749
return self._maybe_cast_for_get_loc(label)
752750

753-
def _get_string_slice(self, key: str):
754-
freq = getattr(self, "freqstr", getattr(self, "inferred_freq", None))
755-
parsed, reso_str = parsing.parse_time_string(key, freq)
756-
reso = Resolution.from_attrname(reso_str)
757-
return self._partial_date_slice(reso, parsed)
758-
759751
def slice_indexer(self, start=None, end=None, step=None, kind=None):
760752
"""
761753
Return indexer for specified label slice.

pandas/core/indexes/period.py

+1-10
Original file line numberDiff line numberDiff line change
@@ -479,12 +479,11 @@ def _maybe_cast_slice_bound(self, label, side: str, kind=lib.no_default):
479479
return Period(label, freq=self.freq)
480480
elif isinstance(label, str):
481481
try:
482-
parsed, reso_str = parse_time_string(label, self.freq)
482+
parsed, reso = self._parse_with_reso(label)
483483
except ValueError as err:
484484
# string cannot be parsed as datetime-like
485485
raise self._invalid_indexer("slice", label) from err
486486

487-
reso = Resolution.from_attrname(reso_str)
488487
lower, upper = self._parsed_string_to_bounds(reso, parsed)
489488
return lower if side == "left" else upper
490489
elif not isinstance(label, self._data._recognized_scalars):
@@ -508,14 +507,6 @@ def _validate_partial_date_slice(self, reso: Resolution):
508507
# why is that check not needed?
509508
raise ValueError
510509

511-
def _get_string_slice(self, key: str):
512-
parsed, reso_str = parse_time_string(key, self.freq)
513-
reso = Resolution.from_attrname(reso_str)
514-
try:
515-
return self._partial_date_slice(reso, parsed)
516-
except KeyError as err:
517-
raise KeyError(key) from err
518-
519510

520511
def period_range(
521512
start=None, end=None, periods: int | None = None, freq=None, name=None

pandas/core/indexes/timedeltas.py

+16-4
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ class TimedeltaIndex(DatetimeTimedeltaMixin):
108108

109109
_data: TimedeltaArray
110110

111+
# Use base class method instead of DatetimeTimedeltaMixin._get_string_slice
112+
_get_string_slice = Index._get_string_slice
113+
111114
# -------------------------------------------------------------------
112115
# Constructors
113116

@@ -197,20 +200,29 @@ def _maybe_cast_slice_bound(self, label, side: str, kind=lib.no_default):
197200

198201
if isinstance(label, str):
199202
try:
200-
parsed = Timedelta(label)
203+
parsed, reso = self._parse_with_reso(label)
201204
except ValueError as err:
202205
# e.g. 'unit abbreviation w/o a number'
203206
raise self._invalid_indexer("slice", label) from err
204207

205-
# The next two lines are analogous to DTI/PI._parsed_str_to_bounds
206-
lower = parsed.round(parsed.resolution_string)
207-
upper = lower + to_offset(parsed.resolution_string) - Timedelta(1, "ns")
208+
lower, upper = self._parsed_string_to_bounds(reso, parsed)
208209
return lower if side == "left" else upper
209210
elif not isinstance(label, self._data._recognized_scalars):
210211
raise self._invalid_indexer("slice", label)
211212

212213
return label
213214

215+
def _parse_with_reso(self, label: str):
216+
# the "with_reso" is a no-op for TimedeltaIndex
217+
parsed = Timedelta(label)
218+
return parsed, None
219+
220+
def _parsed_string_to_bounds(self, reso, parsed: Timedelta):
221+
# reso is unused, included to match signature of DTI/PI
222+
lbound = parsed.round(parsed.resolution_string)
223+
rbound = lbound + to_offset(parsed.resolution_string) - Timedelta(1, "ns")
224+
return lbound, rbound
225+
214226
# -------------------------------------------------------------------
215227

216228
@property

0 commit comments

Comments
 (0)