Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pandas/core/tools/times.py: 14%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

77 statements  

1from __future__ import annotations 

2 

3from datetime import ( 

4 datetime, 

5 time, 

6) 

7from typing import TYPE_CHECKING 

8 

9import numpy as np 

10 

11from pandas._libs.lib import is_list_like 

12 

13from pandas.core.dtypes.generic import ( 

14 ABCIndex, 

15 ABCSeries, 

16) 

17from pandas.core.dtypes.missing import notna 

18 

19if TYPE_CHECKING: 

20 from pandas._typing import DateTimeErrorChoices 

21 

22 

23def to_time( 

24 arg, 

25 format: str | None = None, 

26 infer_time_format: bool = False, 

27 errors: DateTimeErrorChoices = "raise", 

28): 

29 """ 

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 """ 

54 if errors not in ("raise", "coerce"): 

55 raise ValueError("errors must be one of 'raise', or 'coerce'.") 

56 

57 def _convert_listlike(arg, format): 

58 if isinstance(arg, (list, tuple)): 

59 arg = np.array(arg, dtype="O") 

60 

61 elif getattr(arg, "ndim", 1) > 1: 

62 raise TypeError( 

63 "arg must be a string, datetime, list, tuple, 1-d array, or Series" 

64 ) 

65 

66 arg = np.asarray(arg, dtype="O") 

67 

68 if infer_time_format and format is None: 

69 format = _guess_time_format_for_array(arg) 

70 

71 times: list[time | None] = [] 

72 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) 

84 else: 

85 formats = _time_formats[:] 

86 format_found = False 

87 for element in arg: 

88 time_object = None 

89 try: 

90 time_object = time.fromisoformat(element) 

91 except (ValueError, TypeError): 

92 for time_format in formats: 

93 try: 

94 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 break 

101 except (ValueError, TypeError): 

102 continue 

103 

104 if time_object is not None: 

105 times.append(time_object) 

106 elif errors == "raise": 

107 raise ValueError(f"Cannot convert arg {arg} to a time") 

108 else: 

109 times.append(None) 

110 

111 return times 

112 

113 if arg is None: 

114 return arg 

115 elif isinstance(arg, time): 

116 return arg 

117 elif isinstance(arg, ABCSeries): 

118 values = _convert_listlike(arg._values, format) 

119 return arg._constructor(values, index=arg.index, name=arg.name) 

120 elif isinstance(arg, ABCIndex): 

121 return _convert_listlike(arg, format) 

122 elif is_list_like(arg): 

123 return _convert_listlike(arg, format) 

124 

125 return _convert_listlike(np.array([arg]), format)[0] 

126 

127 

128# Fixed time formats for time parsing 

129_time_formats = [ 

130 "%H:%M", 

131 "%H%M", 

132 "%I:%M%p", 

133 "%I%M%p", 

134 "%H:%M:%S", 

135 "%H%M%S", 

136 "%I:%M:%S%p", 

137 "%I%M%S%p", 

138] 

139 

140 

141def _guess_time_format_for_array(arr): 

142 # Try to guess the format based on the first non-NaN element 

143 non_nan_elements = notna(arr).nonzero()[0] 

144 if len(non_nan_elements): 

145 element = arr[non_nan_elements[0]] 

146 for time_format in _time_formats: 

147 try: 

148 datetime.strptime(element, time_format) 

149 return time_format 

150 except ValueError: 

151 pass 

152 

153 return None