@@ -286,19 +286,10 @@ def parse_datetime_string(
286
286
except ValueError :
287
287
pass
288
288
289
- try :
290
- dt = du_parse(date_string, default = _DEFAULT_DATETIME,
291
- dayfirst = dayfirst, yearfirst = yearfirst)
292
- except TypeError :
293
- # following may be raised from dateutil
294
- # TypeError: 'NoneType' object is not iterable
295
- raise ValueError (f' Given date string "{date_string}" not likely a datetime' )
296
- except OverflowError as err:
297
- # with e.g. "08335394550" dateutil raises when trying to pass
298
- # year=8335394550 to datetime.replace
299
- raise OutOfBoundsDatetime(
300
- f' Parsing "{date_string}" to datetime overflows'
301
- ) from err
289
+ dt, _ = dateutil_parse(date_string, default = _DEFAULT_DATETIME,
290
+ dayfirst = dayfirst, yearfirst = yearfirst,
291
+ ignoretz = False )
292
+
302
293
if dt.tzinfo is not None :
303
294
# dateutil can return a datetime with a tzoffset outside of (-24H, 24H)
304
295
# bounds, which is invalid (can be constructed, but raises if we call
@@ -415,15 +406,9 @@ def parse_datetime_string_with_reso(
415
406
except ValueError :
416
407
pass
417
408
418
- try :
419
- parsed, reso = dateutil_parse(date_string, _DEFAULT_DATETIME,
420
- dayfirst = dayfirst, yearfirst = yearfirst,
421
- ignoretz = False )
422
- except (ValueError , OverflowError ) as err:
423
- # TODO: allow raise of errors within instead
424
- raise DateParseError(err)
425
- if parsed is None :
426
- raise DateParseError(f" Could not parse {date_string}" )
409
+ parsed, reso = dateutil_parse(date_string, _DEFAULT_DATETIME,
410
+ dayfirst = dayfirst, yearfirst = yearfirst,
411
+ ignoretz = False )
427
412
return parsed, reso
428
413
429
414
@@ -612,7 +597,7 @@ cpdef quarter_to_myear(int year, int quarter, str freq):
612
597
613
598
cdef dateutil_parse(
614
599
str timestr,
615
- object default,
600
+ datetime default,
616
601
bint ignoretz = False ,
617
602
bint dayfirst = False ,
618
603
bint yearfirst = False ,
@@ -623,13 +608,15 @@ cdef dateutil_parse(
623
608
str attr
624
609
datetime ret
625
610
object res
626
- object reso = None
611
+ str reso = None
627
612
dict repl = {}
628
613
629
614
res, _ = DEFAULTPARSER._parse(timestr, dayfirst = dayfirst, yearfirst = yearfirst)
630
615
631
616
if res is None :
632
- raise ValueError (f" Unknown datetime string format, unable to parse: {timestr}" )
617
+ raise DateParseError(
618
+ f" Unknown datetime string format, unable to parse: {timestr}"
619
+ )
633
620
634
621
for attr in [" year" , " month" , " day" , " hour" ,
635
622
" minute" , " second" , " microsecond" ]:
@@ -639,15 +626,27 @@ cdef dateutil_parse(
639
626
reso = attr
640
627
641
628
if reso is None :
642
- raise ValueError (f" Unable to parse datetime string: {timestr}" )
629
+ raise DateParseError (f" Unable to parse datetime string: {timestr}" )
643
630
644
631
if reso == " microsecond" :
645
632
if repl[" microsecond" ] == 0 :
646
633
reso = " second"
647
634
elif repl[" microsecond" ] % 1000 == 0 :
648
635
reso = " millisecond"
649
636
650
- ret = default.replace(** repl)
637
+ try :
638
+ ret = default.replace(** repl)
639
+ except ValueError as err:
640
+ # e.g. "day is out of range for month"
641
+ # we re-raise to match dateutil's exception message
642
+ raise DateParseError(str (err) + " : " + timestr) from err
643
+ except OverflowError as err:
644
+ # with e.g. "08335394550" dateutil raises when trying to pass
645
+ # year=8335394550 to datetime.replace
646
+ raise OutOfBoundsDatetime(
647
+ f' Parsing "{timestr}" to datetime overflows'
648
+ ) from err
649
+
651
650
if res.weekday is not None and not res.day:
652
651
ret = ret + relativedelta.relativedelta(weekday = res.weekday)
653
652
if not ignoretz:
0 commit comments