1
1
from __future__ import annotations
2
-
3
- from datetime import (
4
- datetime ,
5
- time ,
6
- )
7
- from typing import TYPE_CHECKING
8
-
2
+ from datetime import datetime , time
3
+ from typing import TYPE_CHECKING , List , Union
9
4
import numpy as np
10
-
11
5
from pandas ._libs .lib import is_list_like
12
-
13
- from pandas .core .dtypes .generic import (
14
- ABCIndex ,
15
- ABCSeries ,
16
- )
6
+ from pandas .core .dtypes .generic import ABCIndex , ABCSeries
17
7
from pandas .core .dtypes .missing import notna
18
8
19
9
if TYPE_CHECKING :
20
10
from pandas ._typing import DateTimeErrorChoices
21
11
22
12
23
13
def to_time (
24
- arg ,
25
- format : str | None = None ,
26
- infer_time_format : bool = False ,
27
- errors : DateTimeErrorChoices = "raise" ,
14
+ arg ,
15
+ format : Union [str , List [str ], None ] = None ,
16
+ infer_time_format : bool = False ,
17
+ errors : DateTimeErrorChoices = "raise" ,
18
+ custom_formats : List [str ] = None ,
28
19
):
29
20
"""
30
- Parse time strings to time objects using fixed strptime formats ("%H:%M",
31
- "%H%M", "%I:%M%p", "%I%M%p", "%H:%M:%S", "%H%M%S", "%I:%M:%S%p",
32
- "%I%M%S%p")
33
-
34
- Use infer_time_format if all the strings are in the same format to speed
35
- up conversion.
36
-
37
- Parameters
38
- ----------
39
- arg : string in time format, datetime.time, list, tuple, 1-d array, Series
40
- format : str, default None
41
- Format used to convert arg into a time object. If None, fixed formats
42
- are used.
43
- infer_time_format: bool, default False
44
- Infer the time format based on the first non-NaN element. If all
45
- strings are in the same format, this will speed up conversion.
46
- errors : {'raise', 'coerce'}, default 'raise'
47
- - If 'raise', then invalid parsing will raise an exception
48
- - If 'coerce', then invalid parsing will be set as None
49
-
50
- Returns
51
- -------
52
- datetime.time
53
- """
21
+ Parse time strings to time objects using fixed strptime formats ("%H:%M",
22
+ "%H%M", "%I:%M%p", "%I%M%p", "%H:%M:%S", "%H%M%S", "%I:%M:%S%p",
23
+ "%I%M%S%p") and additional custom formats.
24
+
25
+ Use infer_time_format if all the strings are in the same format to speed
26
+ up conversion.
27
+
28
+ Parameters
29
+ ----------
30
+ arg : string in time format, datetime.time, list, tuple, 1-d array, Series
31
+ format : str or list of str, default None
32
+ Format(s) used to convert arg into a time object. If None, fixed
33
+ formats are used.
34
+ infer_time_format: bool, default False
35
+ Infer the time format based on the first non-NaN element. If all
36
+ strings are in the same format, this will speed up conversion.
37
+ errors : {'raise', 'coerce'}, default 'raise'
38
+ - If 'raise', then invalid parsing will raise an exception
39
+ - If 'coerce', then invalid parsing will be set as None
40
+ custom_formats : list of str, default None
41
+ Additional custom time formats to use.
42
+ Returns
43
+ -------
44
+ datetime.time or list of datetime.time
45
+ """
54
46
if errors not in ("raise" , "coerce" ):
55
47
raise ValueError ("errors must be one of 'raise', or 'coerce'." )
56
48
@@ -62,28 +54,37 @@ def _convert_listlike(arg, format):
62
54
raise TypeError (
63
55
"arg must be a string, datetime, list, tuple, 1-d array, or Series"
64
56
)
65
-
66
57
arg = np .asarray (arg , dtype = "O" )
67
58
68
59
if infer_time_format and format is None :
69
60
format = _guess_time_format_for_array (arg )
70
-
71
- times : list [time | None ] = []
61
+ times = []
72
62
if format is not None :
73
- for element in arg :
74
- try :
75
- times .append (datetime .strptime (element , format ).time ())
76
- except (ValueError , TypeError ) as err :
77
- if errors == "raise" :
78
- msg = (
79
- f"Cannot convert { element } to a time with given "
80
- f"format { format } "
81
- )
82
- raise ValueError (msg ) from err
83
- times .append (None )
63
+ if isinstance (format , list ):
64
+ for element in arg :
65
+ for fmt in format :
66
+ try :
67
+ times .append (datetime .strptime (element , fmt ).time ())
68
+ break
69
+ except (ValueError , TypeError ):
70
+ continue
71
+ else :
72
+ if errors == "raise" :
73
+ msg = (
74
+ f"Cannot convert { element } to a time with given " f"formats { format } " )
75
+ raise ValueError (msg )
76
+ times .append (None )
77
+ else :
78
+ for element in arg :
79
+ try :
80
+ times .append (datetime .strptime (element , format ).time ())
81
+ except (ValueError , TypeError ) as err :
82
+ if errors == "raise" :
83
+ msg = (f"Cannot convert { element } to a time withgiven " f"format { format } " )
84
+ raise ValueError (msg ) from err
85
+ times .append (None )
84
86
else :
85
- formats = _time_formats [:]
86
- format_found = False
87
+ formats = _time_formats + (custom_formats or [])
87
88
for element in arg :
88
89
time_object = None
89
90
try :
@@ -92,22 +93,15 @@ def _convert_listlike(arg, format):
92
93
for time_format in formats :
93
94
try :
94
95
time_object = datetime .strptime (element , time_format ).time ()
95
- if not format_found :
96
- # Put the found format in front
97
- fmt = formats .pop (formats .index (time_format ))
98
- formats .insert (0 , fmt )
99
- format_found = True
100
96
break
101
97
except (ValueError , TypeError ):
102
98
continue
103
-
104
99
if time_object is not None :
105
100
times .append (time_object )
106
101
elif errors == "raise" :
107
102
raise ValueError (f"Cannot convert arg { arg } to a time" )
108
103
else :
109
104
times .append (None )
110
-
111
105
return times
112
106
113
107
if arg is None :
@@ -121,7 +115,6 @@ def _convert_listlike(arg, format):
121
115
return _convert_listlike (arg , format )
122
116
elif is_list_like (arg ):
123
117
return _convert_listlike (arg , format )
124
-
125
118
return _convert_listlike (np .array ([arg ]), format )[0 ]
126
119
127
120
@@ -149,5 +142,4 @@ def _guess_time_format_for_array(arr):
149
142
return time_format
150
143
except ValueError :
151
144
pass
152
-
153
145
return None
0 commit comments