@@ -116,21 +116,22 @@ def _is_iso_format_string(date_str: str) -> bool:
116116 Check if a date string follows ISO8601 format.
117117
118118 ISO format must start with a 4-digit year (YYYY), optionally followed by
119- month and day with consistent separators .
119+ hyphen-separated month and day or 'T' for time component .
120120
121121 Examples of ISO format (True):
122+ - 2024
123+ - 2024-01
122124 - 2024-01-10
123- - 2024/01/10
124- - 2024 01 10
125125 - 2024-01-10T00:00:00
126126
127127 Examples of non-ISO format (False):
128+ - 2024/01/10 (/ separator)
129+ - 2024 01 10 (space separator)
128130 - 01/10/2024 (MM/DD/YYYY)
129131 - 10/01/2024 (DD/MM/YYYY)
130132 - 01-10-2024 (MM-DD-YYYY)
131133 """
132- # ISO format must start with 4-digit year followed by separator (-, /, ., or space)
133- return re .match (r"^\d{4}[-/. ]" , date_str ) is not None
134+ return re .match (r"^\d{4}(?:-|T|$)" , date_str ) is not None
134135
135136
136137@inherit_names (
@@ -722,6 +723,23 @@ def check_str_or_none(point) -> bool:
722723 # GH#33146 if start and end are combinations of str and None and Index is not
723724 # monotonic, we can not use Index.slice_indexer because it does not honor the
724725 # actual elements, is only searching for start and end
726+ # GH#58302 - Deprecate non-ISO string formats in .loc indexing
727+ if isinstance (start , str ) and not _is_iso_format_string (start ):
728+ msg = (
729+ "Parsing non-ISO datetime strings in .loc is deprecated "
730+ "and will be removed in a future version. Use ISO format "
731+ f"(YYYY-MM-DD) instead. Got '{ start } '."
732+ )
733+ warnings .warn (msg , Pandas4Warning , stacklevel = find_stack_level ())
734+
735+ if isinstance (end , str ) and not _is_iso_format_string (end ):
736+ msg = (
737+ "Parsing non-ISO datetime strings in .loc is deprecated "
738+ "and will be removed in a future version. Use ISO format "
739+ f"(YYYY-MM-DD) instead. Got '{ end } '."
740+ )
741+ warnings .warn (msg , Pandas4Warning , stacklevel = find_stack_level ())
742+
725743 if (
726744 check_str_or_none (start )
727745 or check_str_or_none (end )
@@ -733,31 +751,12 @@ def check_str_or_none(point) -> bool:
733751 in_index = True
734752 if start is not None :
735753 start_casted = self ._maybe_cast_slice_bound (start , "left" )
736-
737- # GH#58302 - Deprecate non-ISO string formats in .loc indexing
738- if isinstance (start , str ) and not _is_iso_format_string (start ):
739- msg = (
740- "Parsing non-ISO datetime strings in .loc is deprecated "
741- "and will be removed in a future version. Use ISO format "
742- f"(YYYY-MM-DD) instead. Got '{ start } '."
743- )
744- warnings .warn (msg , Pandas4Warning , stacklevel = find_stack_level ())
745-
746754 mask = start_casted <= self
747755 in_index &= (start_casted == self ).any ()
748756
749757 if end is not None :
750758 end_casted = self ._maybe_cast_slice_bound (end , "right" )
751759
752- # GH#58302 - Deprecate non-ISO string formats in .loc indexing
753- if isinstance (end , str ) and not _is_iso_format_string (end ):
754- msg = (
755- "Parsing non-ISO datetime strings in .loc is deprecated "
756- "and will be removed in a future version. Use ISO format "
757- f"(YYYY-MM-DD) instead. Got '{ end } '."
758- )
759- warnings .warn (msg , Pandas4Warning , stacklevel = find_stack_level ())
760-
761760 mask = (self <= end_casted ) & mask
762761 in_index &= (end_casted == self ).any ()
763762
0 commit comments