@@ -7,7 +7,7 @@ import numpy as np
7
7
cnp.import_array()
8
8
9
9
10
- from cpython cimport PyFloat_Check
10
+ from cpython cimport PyFloat_Check, PyUnicode_Check
11
11
12
12
from util cimport (is_integer_object, is_float_object, is_string_object,
13
13
is_datetime64_object)
@@ -56,6 +56,8 @@ from tslibs.timestamps cimport (create_timestamp_from_ts,
56
56
_NS_UPPER_BOUND, _NS_LOWER_BOUND)
57
57
from tslibs.timestamps import Timestamp
58
58
59
+ cdef bint PY2 = str == bytes
60
+
59
61
60
62
cdef inline object create_datetime_from_ts(
61
63
int64_t value, pandas_datetimestruct dts,
@@ -549,23 +551,23 @@ cpdef array_to_datetime(ndarray[object] values, errors='raise',
549
551
raise
550
552
551
553
elif PyDate_Check(val):
554
+ seen_datetime = 1
552
555
iresult[i] = pydate_to_dt64(val, & dts)
553
556
try :
554
557
check_dts_bounds(& dts)
555
- seen_datetime = 1
556
558
except ValueError :
557
559
if is_coerce:
558
560
iresult[i] = NPY_NAT
559
561
continue
560
562
raise
561
563
562
564
elif is_datetime64_object(val):
565
+ seen_datetime = 1
563
566
if get_datetime64_value(val) == NPY_NAT:
564
567
iresult[i] = NPY_NAT
565
568
else :
566
569
try :
567
570
iresult[i] = get_datetime64_nanos(val)
568
- seen_datetime = 1
569
571
except ValueError :
570
572
if is_coerce:
571
573
iresult[i] = NPY_NAT
@@ -574,66 +576,44 @@ cpdef array_to_datetime(ndarray[object] values, errors='raise',
574
576
575
577
elif is_integer_object(val) or is_float_object(val):
576
578
# these must be ns unit by-definition
579
+ seen_integer = 1
577
580
578
581
if val != val or val == NPY_NAT:
579
582
iresult[i] = NPY_NAT
580
583
elif is_raise or is_ignore:
581
584
iresult[i] = val
582
- seen_integer = 1
583
585
else :
584
586
# coerce
585
587
# we now need to parse this as if unit='ns'
586
588
# we can ONLY accept integers at this point
587
589
# if we have previously (or in future accept
588
590
# datetimes/strings, then we must coerce)
589
- seen_integer = 1
590
591
try :
591
592
iresult[i] = cast_from_unit(val, ' ns' )
592
593
except :
593
594
iresult[i] = NPY_NAT
594
595
595
596
elif is_string_object(val):
596
597
# string
598
+ seen_string = 1
597
599
598
600
if len (val) == 0 or val in nat_strings:
599
601
iresult[i] = NPY_NAT
600
602
continue
601
-
602
- seen_string = 1
603
+ if PyUnicode_Check(val) and PY2:
604
+ val = val.encode( ' utf-8 ' )
603
605
604
606
try :
605
607
_string_to_dts(val, & dts, & out_local, & out_tzoffset)
606
- value = dtstruct_to_dt64(& dts)
607
- if out_local == 1 :
608
- tz = pytz.FixedOffset(out_tzoffset)
609
- value = tz_convert_single(value, tz, ' UTC' )
610
- iresult[i] = value
611
- check_dts_bounds(& dts)
612
- except OutOfBoundsDatetime:
613
- # GH#19382 for just-barely-OutOfBounds falling back to
614
- # dateutil parser will return incorrect result because
615
- # it will ignore nanoseconds
616
- if require_iso8601:
617
- if _parse_today_now(val, & iresult[i]):
618
- continue
619
- elif is_coerce:
620
- iresult[i] = NPY_NAT
621
- continue
622
- elif is_raise:
623
- raise ValueError (" time data {val} doesn't match "
624
- " format specified"
625
- .format(val = val))
626
- return values
627
- elif is_coerce:
628
- iresult[i] = NPY_NAT
629
- continue
630
- raise
631
608
except ValueError :
632
- # if requiring iso8601 strings, skip trying other formats
633
- if require_iso8601:
634
- if _parse_today_now(val, & iresult[i]):
635
- continue
636
- elif is_coerce:
609
+ # A ValueError at this point is a _parsing_ error
610
+ # specifically _not_ OutOfBoundsDatetime
611
+ if _parse_today_now(val, & iresult[i]):
612
+ continue
613
+ elif require_iso8601:
614
+ # if requiring iso8601 strings, skip trying
615
+ # other formats
616
+ if is_coerce:
637
617
iresult[i] = NPY_NAT
638
618
continue
639
619
elif is_raise:
@@ -646,8 +626,6 @@ cpdef array_to_datetime(ndarray[object] values, errors='raise',
646
626
py_dt = parse_datetime_string(val, dayfirst = dayfirst,
647
627
yearfirst = yearfirst)
648
628
except Exception :
649
- if _parse_today_now(val, & iresult[i]):
650
- continue
651
629
if is_coerce:
652
630
iresult[i] = NPY_NAT
653
631
continue
@@ -656,16 +634,42 @@ cpdef array_to_datetime(ndarray[object] values, errors='raise',
656
634
try :
657
635
_ts = convert_datetime_to_tsobject(py_dt, None )
658
636
iresult[i] = _ts.value
659
- except ValueError :
637
+ except OutOfBoundsDatetime :
660
638
if is_coerce:
661
639
iresult[i] = NPY_NAT
662
640
continue
663
641
raise
664
642
except :
643
+ # TODO: What exception are we concerned with here?
665
644
if is_coerce:
666
645
iresult[i] = NPY_NAT
667
646
continue
668
647
raise
648
+ else :
649
+ # No error raised by string_to_dts, pick back up
650
+ # where we left off
651
+ value = dtstruct_to_dt64(& dts)
652
+ if out_local == 1 :
653
+ tz = pytz.FixedOffset(out_tzoffset)
654
+ value = tz_convert_single(value, tz, ' UTC' )
655
+ iresult[i] = value
656
+ try :
657
+ check_dts_bounds(& dts)
658
+ except OutOfBoundsDatetime:
659
+ # GH#19382 for just-barely-OutOfBounds falling back to
660
+ # dateutil parser will return incorrect result because
661
+ # it will ignore nanoseconds
662
+ if is_coerce:
663
+ iresult[i] = NPY_NAT
664
+ continue
665
+ elif require_iso8601:
666
+ if is_raise:
667
+ raise ValueError (" time data {val} doesn't "
668
+ " match format specified"
669
+ .format(val = val))
670
+ return values
671
+ raise
672
+
669
673
else :
670
674
if is_coerce:
671
675
iresult[i] = NPY_NAT
0 commit comments