@@ -71,6 +71,196 @@ cdef dict _parse_code_table = {"y": 0,
71
71
" V" : 21 ,
72
72
" u" : 22 }
73
73
74
+ cdef strptime(
75
+ val,
76
+ str fmt,
77
+ bint exact,
78
+ format_regex,
79
+ locale_time,
80
+ npy_datetimestruct dts,
81
+ ):
82
+ if exact:
83
+ found = format_regex.match(val)
84
+ if not found:
85
+ raise ValueError (f" time data '{val}' does not match "
86
+ f" format '{fmt}' (match)" )
87
+ if len (val) != found.end():
88
+ raise ValueError (f" unconverted data remains: {val[found.end():]}" )
89
+
90
+ # search
91
+ else :
92
+ found = format_regex.search(val)
93
+ if not found:
94
+ raise ValueError (f" time data {repr(val)} does not match format "
95
+ f" {repr(fmt)} (search)" )
96
+
97
+ iso_year = - 1
98
+ year = 1900
99
+ month = day = 1
100
+ hour = minute = second = ns = us = 0
101
+ tz = None
102
+ # Default to -1 to signify that values not known; not critical to have,
103
+ # though
104
+ iso_week = week_of_year = - 1
105
+ week_of_year_start = - 1
106
+ # weekday and julian defaulted to -1 so as to signal need to calculate
107
+ # values
108
+ weekday = julian = - 1
109
+ found_dict = found.groupdict()
110
+ for group_key in found_dict.iterkeys():
111
+ # Directives not explicitly handled below:
112
+ # c, x, X
113
+ # handled by making out of other directives
114
+ # U, W
115
+ # worthless without day of the week
116
+ parse_code = _parse_code_table[group_key]
117
+
118
+ if parse_code == 0 :
119
+ year = int (found_dict[" y" ])
120
+ # Open Group specification for strptime() states that a %y
121
+ # value in the range of [00, 68] is in the century 2000, while
122
+ # [69,99] is in the century 1900
123
+ if year <= 68 :
124
+ year += 2000
125
+ else :
126
+ year += 1900
127
+ elif parse_code == 1 :
128
+ year = int (found_dict[" Y" ])
129
+ elif parse_code == 2 :
130
+ month = int (found_dict[" m" ])
131
+ # elif group_key == 'B':
132
+ elif parse_code == 3 :
133
+ month = locale_time.f_month.index(found_dict[" B" ].lower())
134
+ # elif group_key == 'b':
135
+ elif parse_code == 4 :
136
+ month = locale_time.a_month.index(found_dict[" b" ].lower())
137
+ # elif group_key == 'd':
138
+ elif parse_code == 5 :
139
+ day = int (found_dict[" d" ])
140
+ # elif group_key == 'H':
141
+ elif parse_code == 6 :
142
+ hour = int (found_dict[" H" ])
143
+ elif parse_code == 7 :
144
+ hour = int (found_dict[" I" ])
145
+ ampm = found_dict.get(" p" , " " ).lower()
146
+ # If there was no AM/PM indicator, we'll treat this like AM
147
+ if ampm in (" " , locale_time.am_pm[0 ]):
148
+ # We're in AM so the hour is correct unless we're
149
+ # looking at 12 midnight.
150
+ # 12 midnight == 12 AM == hour 0
151
+ if hour == 12 :
152
+ hour = 0
153
+ elif ampm == locale_time.am_pm[1 ]:
154
+ # We're in PM so we need to add 12 to the hour unless
155
+ # we're looking at 12 noon.
156
+ # 12 noon == 12 PM == hour 12
157
+ if hour != 12 :
158
+ hour += 12
159
+ elif parse_code == 8 :
160
+ minute = int (found_dict[" M" ])
161
+ elif parse_code == 9 :
162
+ second = int (found_dict[" S" ])
163
+ elif parse_code == 10 :
164
+ s = found_dict[" f" ]
165
+ # Pad to always return nanoseconds
166
+ s += " 0" * (9 - len (s))
167
+ us = long (s)
168
+ ns = us % 1000
169
+ us = us // 1000
170
+ elif parse_code == 11 :
171
+ weekday = locale_time.f_weekday.index(found_dict[" A" ].lower())
172
+ elif parse_code == 12 :
173
+ weekday = locale_time.a_weekday.index(found_dict[" a" ].lower())
174
+ elif parse_code == 13 :
175
+ weekday = int (found_dict[" w" ])
176
+ if weekday == 0 :
177
+ weekday = 6
178
+ else :
179
+ weekday -= 1
180
+ elif parse_code == 14 :
181
+ julian = int (found_dict[" j" ])
182
+ elif parse_code == 15 or parse_code == 16 :
183
+ week_of_year = int (found_dict[group_key])
184
+ if group_key == " U" :
185
+ # U starts week on Sunday.
186
+ week_of_year_start = 6
187
+ else :
188
+ # W starts week on Monday.
189
+ week_of_year_start = 0
190
+ elif parse_code == 17 :
191
+ tz = pytz.timezone(found_dict[" Z" ])
192
+ elif parse_code == 19 :
193
+ tz = parse_timezone_directive(found_dict[" z" ])
194
+ elif parse_code == 20 :
195
+ iso_year = int (found_dict[" G" ])
196
+ elif parse_code == 21 :
197
+ iso_week = int (found_dict[" V" ])
198
+ elif parse_code == 22 :
199
+ weekday = int (found_dict[" u" ])
200
+ weekday -= 1
201
+
202
+ # don't assume default values for ISO week/year
203
+ if iso_year != - 1 :
204
+ if iso_week == - 1 or weekday == - 1 :
205
+ raise ValueError (" ISO year directive '%G ' must be used with "
206
+ " the ISO week directive '%V ' and a weekday "
207
+ " directive '%A ', '%a ', '%w ', or '%u '." )
208
+ if julian != - 1 :
209
+ raise ValueError (" Day of the year directive '%j ' is not "
210
+ " compatible with ISO year directive '%G '. "
211
+ " Use '%Y ' instead." )
212
+ elif year != - 1 and week_of_year == - 1 and iso_week != - 1 :
213
+ if weekday == - 1 :
214
+ raise ValueError (" ISO week directive '%V ' must be used with "
215
+ " the ISO year directive '%G ' and a weekday "
216
+ " directive '%A ', '%a ', '%w ', or '%u '." )
217
+ else :
218
+ raise ValueError (" ISO week directive '%V ' is incompatible with "
219
+ " the year directive '%Y '. Use the ISO year "
220
+ " '%G ' instead." )
221
+
222
+ # If we know the wk of the year and what day of that wk, we can figure
223
+ # out the Julian day of the year.
224
+ if julian == - 1 and weekday != - 1 :
225
+ if week_of_year != - 1 :
226
+ week_starts_Mon = week_of_year_start == 0
227
+ julian = _calc_julian_from_U_or_W(year, week_of_year, weekday,
228
+ week_starts_Mon)
229
+ elif iso_year != - 1 and iso_week != - 1 :
230
+ year, julian = _calc_julian_from_V(iso_year, iso_week,
231
+ weekday + 1 )
232
+ # Cannot pre-calculate date() since can change in Julian
233
+ # calculation and thus could have different value for the day of the wk
234
+ # calculation.
235
+ if julian == - 1 :
236
+ # Need to add 1 to result since first day of the year is 1, not
237
+ # 0.
238
+ ordinal = date(year, month, day).toordinal()
239
+ julian = ordinal - date(year, 1 , 1 ).toordinal() + 1
240
+ else :
241
+ # Assume that if they bothered to include Julian day it will
242
+ # be accurate.
243
+ datetime_result = date.fromordinal(
244
+ (julian - 1 ) + date(year, 1 , 1 ).toordinal())
245
+ year = datetime_result.year
246
+ month = datetime_result.month
247
+ day = datetime_result.day
248
+ if weekday == - 1 :
249
+ weekday = date(year, month, day).weekday()
250
+
251
+ dts.year = year
252
+ dts.month = month
253
+ dts.day = day
254
+ dts.hour = hour
255
+ dts.min = minute
256
+ dts.sec = second
257
+ dts.us = us
258
+ dts.ps = ns * 1000
259
+
260
+ iresult = npy_datetimestruct_to_datetime(NPY_FR_ns, & dts)
261
+ check_dts_bounds(& dts)
262
+ return iresult, tz
263
+
74
264
75
265
def array_strptime (
76
266
ndarray[object] values ,
0 commit comments