@@ -29,7 +29,8 @@ cimport cython
29
29
import numpy as np
30
30
from numpy cimport ndarray, int64_t
31
31
32
- from datetime import date as datetime_date
32
+ from datetime import (date as datetime_date, timedelta as datetime_timedelta,
33
+ timezone as datetime_timezone)
33
34
from cpython.datetime cimport datetime
34
35
35
36
from np_datetime cimport (check_dts_bounds,
@@ -58,6 +59,7 @@ def array_strptime(ndarray[object] values, object fmt,
58
59
Py_ssize_t i, n = len (values)
59
60
pandas_datetimestruct dts
60
61
ndarray[int64_t] iresult
62
+ ndarray[object ] results_tz
61
63
int year, month, day, minute, hour, second, weekday, julian, tz
62
64
int week_of_year, week_of_year_start
63
65
int64_t us, ns
@@ -109,6 +111,8 @@ def array_strptime(ndarray[object] values, object fmt,
109
111
result = np.empty(n, dtype = ' M8[ns]' )
110
112
iresult = result.view(' i8' )
111
113
114
+ results_tz = np.empty(n, dtype = ' object' )
115
+
112
116
dts.us = dts.ps = dts.as = 0
113
117
114
118
cdef dict _parse_code_table = {
@@ -130,7 +134,8 @@ def array_strptime(ndarray[object] values, object fmt,
130
134
' U' : 15 ,
131
135
' W' : 16 ,
132
136
' Z' : 17 ,
133
- ' p' : 18 # just an additional key, works only with I
137
+ ' p' : 18 , # just an additional key, works only with I
138
+ ' z' : 19 ,
134
139
}
135
140
cdef int parse_code
136
141
@@ -177,6 +182,8 @@ def array_strptime(ndarray[object] values, object fmt,
177
182
month = day = 1
178
183
hour = minute = second = ns = us = 0
179
184
tz = - 1
185
+ gmtoff = None
186
+ gmtoff_fraction = 0
180
187
# Default to -1 to signify that values not known; not critical to have,
181
188
# though
182
189
week_of_year = - 1
@@ -281,6 +288,32 @@ def array_strptime(ndarray[object] values, object fmt,
281
288
else :
282
289
tz = value
283
290
break
291
+ elif parse_code == 19 :
292
+ z = found_dict[' z' ]
293
+ if z == ' Z' :
294
+ gmtoff = 0
295
+ else :
296
+ if z[3 ] == ' :' :
297
+ z = z[:3 ] + z[4 :]
298
+ if len (z) > 5 :
299
+ if z[5 ] != ' :' :
300
+ msg = " Unconsistent use of : in {0}"
301
+ raise ValueError (msg.format(found_dict[' z' ]))
302
+ z = z[:5 ] + z[6 :]
303
+ hours = int (z[1 :3 ])
304
+ minutes = int (z[3 :5 ])
305
+ seconds = int (z[5 :7 ] or 0 )
306
+ gmtoff = (hours * 60 * 60 ) + (minutes * 60 ) + seconds
307
+ gmtoff_remainder = z[8 :]
308
+ # Pad to always return microseconds.
309
+ pad_number = 6 - len (gmtoff_remainder)
310
+ gmtoff_remainder_padding = " 0" * pad_number
311
+ gmtoff_fraction = int (gmtoff_remainder +
312
+ gmtoff_remainder_padding)
313
+ if z.startswith(" -" ):
314
+ gmtoff = - gmtoff
315
+ gmtoff_fraction = - gmtoff_fraction
316
+
284
317
# If we know the wk of the year and what day of that wk, we can figure
285
318
# out the Julian day of the year.
286
319
if julian == - 1 and week_of_year != - 1 and weekday != - 1 :
@@ -330,7 +363,17 @@ def array_strptime(ndarray[object] values, object fmt,
330
363
continue
331
364
raise
332
365
333
- return result
366
+ if gmtoff is not None :
367
+ tzdelta = datetime_timedelta(seconds = gmtoff,
368
+ microseconds = gmtoff_fraction)
369
+ tzname = found_dict.get(' Z' )
370
+ if tzname:
371
+ tzinfo = datetime_timezone(tzdelta, tzname)
372
+ else :
373
+ tzinfo = datetime_timezone(tzdelta, tzname)
374
+ results_tz[i] = tzinfo
375
+
376
+ return result, results_tz
334
377
335
378
336
379
""" _getlang, LocaleTime, TimeRE, _calc_julian_from_U_or_W are vendored
@@ -538,6 +581,7 @@ class TimeRE(dict):
538
581
# XXX: Does 'Y' need to worry about having less or more than
539
582
# 4 digits?
540
583
' Y' : r " ( ?P<Y> \d\d\d\d ) " ,
584
+ ' z' : r " ( ?P<z> [+- ]\d\d :? [0-5 ]\d ( :? [0-5 ]\d ( \. \d {1,6} ) ? ) ? | Z) " ,
541
585
' A' : self .__seqToRE(self .locale_time.f_weekday, ' A' ),
542
586
' a' : self .__seqToRE(self .locale_time.a_weekday, ' a' ),
543
587
' B' : self .__seqToRE(self .locale_time.f_month[1 :], ' B' ),
0 commit comments