@@ -236,25 +236,6 @@ cpdef inline int64_t cast_from_unit(object ts, object unit) except? -1:
236
236
return < int64_t> (base * m) + < int64_t> (frac * m)
237
237
238
238
239
- cpdef match_iso_format(object ts):
240
- """
241
- Match a provided string against an ISO 8601 pattern, providing a group for
242
- each ``Timedelta`` component.
243
- """
244
- pater = re.compile(r """ P
245
- ( ?P<days> -? [0-9 ]* ) DT
246
- ( ?P<hours> [0-9 ]{1,2} ) H
247
- ( ?P<minutes> [0-9 ]{1,2} ) M
248
- ( ?P<seconds> [0-9 ]{0,2} )
249
- ( \.
250
- ( ?P<milliseconds> [0-9 ]{0,3} )
251
- ( ?P<microseconds> [0-9 ]{0,3} )
252
- ( ?P<nanoseconds> [0-9 ]{0,3} )
253
- ) ? S""" , re.VERBOSE)
254
-
255
- return re.match(pater, ts)
256
-
257
-
258
239
cdef inline parse_timedelta_string(object ts):
259
240
"""
260
241
Parse a regular format timedelta string. Return an int64_t (in ns)
@@ -526,31 +507,50 @@ def _binary_op_method_timedeltalike(op, name):
526
507
# ----------------------------------------------------------------------
527
508
# Timedelta Construction
528
509
529
- def _value_from_iso_match (match ):
510
+ iso_pater = re.compile(r """ P
511
+ ( ?P<days> -? [0-9 ]* ) DT
512
+ ( ?P<hours> [0-9 ]{1,2} ) H
513
+ ( ?P<minutes> [0-9 ]{1,2} ) M
514
+ ( ?P<seconds> [0-9 ]{0,2} )
515
+ ( \.
516
+ ( ?P<milliseconds> [0-9 ]{1,3} )
517
+ ( ?P<microseconds> [0-9 ]{0,3} )
518
+ ( ?P<nanoseconds> [0-9 ]{0,3} )
519
+ ) ? S""" , re.VERBOSE)
520
+
521
+
522
+ cdef int64_t parse_iso_format_string(object iso_fmt):
530
523
"""
531
524
Extracts and cleanses the appropriate values from a match object with
532
525
groups for each component of an ISO 8601 duration
533
526
534
527
Parameters
535
528
----------
536
- match:
537
- Regular expression with groups for each component of an ISO 8601
538
- duration
529
+ iso_fmt:
530
+ ISO 8601 Duration formatted string
539
531
540
532
Returns
541
533
-------
542
- int
543
- Precision in nanoseconds of matched ISO 8601 duration
534
+ ns: int64_t
535
+ Precision in nanoseconds of matched ISO 8601 duration, or -1 if
536
+ `iso_fmt` cannot be parsed
544
537
"""
545
- match_dict = {k: v for k, v in match.groupdict().items() if v}
546
- for comp in [' milliseconds' , ' microseconds' , ' nanoseconds' ]:
547
- if comp in match_dict:
548
- match_dict[comp] = ' {:0<3}' .format(match_dict[comp])
549
538
550
- match_dict = {k: int (v) for k, v in match_dict.items()}
551
- nano = match_dict.pop(' nanoseconds' , 0 )
539
+ cdef int64_t ns = 0
540
+
541
+ match = re.match(iso_pater, iso_fmt)
542
+ if match:
543
+ match_dict = match.groupdict(default = ' 0' )
544
+ for comp in [' milliseconds' , ' microseconds' , ' nanoseconds' ]:
545
+ match_dict[comp] = ' {:0<3}' .format(match_dict[comp])
546
+
547
+ for k, v in match_dict.items():
548
+ ns += timedelta_from_spec(v, ' 0' , k)
552
549
553
- return nano + convert_to_timedelta64(timedelta(** match_dict), ' ns' )
550
+ else :
551
+ ns = - 1
552
+
553
+ return ns
554
554
555
555
556
556
cdef _to_py_int_float(v):
@@ -872,11 +872,16 @@ class Timedelta(_Timedelta):
872
872
if isinstance (value, Timedelta):
873
873
value = value.value
874
874
elif is_string_object(value):
875
- if len (value) > 0 and value[0 ] == ' P' : # hackish
876
- match = match_iso_format(value)
877
- value = _value_from_iso_match(match)
875
+ if len (value) > 0 and value[0 ] == ' P' :
876
+ iso_val = parse_iso_format_string(value)
877
+ if iso_val == - 1 :
878
+ raise ValueError (" Invalid ISO 8601 Duration format - "
879
+ " {}" .format(value))
880
+ else :
881
+ value = iso_val
878
882
else :
879
- value = np.timedelta64(parse_timedelta_string(value))
883
+ value = parse_timedelta_string(value)
884
+ value = np.timedelta64(value)
880
885
elif PyDelta_Check(value):
881
886
value = convert_to_timedelta64(value, ' ns' )
882
887
elif is_timedelta64_object(value):
0 commit comments