@@ -236,25 +236,6 @@ cpdef inline int64_t cast_from_unit(object ts, object unit) except? -1:
236236 return < int64_t> (base * m) + < int64_t> (frac * m)
237237
238238
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-
258239cdef inline parse_timedelta_string(object ts):
259240 """
260241 Parse a regular format timedelta string. Return an int64_t (in ns)
@@ -526,31 +507,50 @@ def _binary_op_method_timedeltalike(op, name):
526507# ----------------------------------------------------------------------
527508# Timedelta Construction
528509
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):
530523 """
531524 Extracts and cleanses the appropriate values from a match object with
532525 groups for each component of an ISO 8601 duration
533526
534527 Parameters
535528 ----------
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
539531
540532 Returns
541533 -------
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
544537 """
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])
549538
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)
552549
553- return nano + convert_to_timedelta64(timedelta(** match_dict), ' ns' )
550+ else :
551+ ns = - 1
552+
553+ return ns
554554
555555
556556cdef _to_py_int_float(v):
@@ -872,11 +872,16 @@ class Timedelta(_Timedelta):
872872 if isinstance (value, Timedelta):
873873 value = value.value
874874 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
878882 else :
879- value = np.timedelta64(parse_timedelta_string(value))
883+ value = parse_timedelta_string(value)
884+ value = np.timedelta64(value)
880885 elif PyDelta_Check(value):
881886 value = convert_to_timedelta64(value, ' ns' )
882887 elif is_timedelta64_object(value):
0 commit comments