@@ -51,7 +51,7 @@ from pandas._libs.tslibs.parsing import parse_datetime_string
51
51
from pandas._libs.tslibs.conversion cimport (
52
52
_TSObject,
53
53
cast_from_unit,
54
- convert_datetime_to_tsobject ,
54
+ convert_str_to_tsobject ,
55
55
convert_timezone,
56
56
get_datetime64_nanos,
57
57
parse_pydatetime,
@@ -482,20 +482,15 @@ cpdef array_to_datetime(
482
482
object val, tz
483
483
ndarray[int64_t] iresult
484
484
npy_datetimestruct dts
485
- NPY_DATETIMEUNIT out_bestunit
486
485
bint utc_convert = bool (utc)
487
486
bint seen_datetime_offset = False
488
487
bint is_raise = errors== " raise"
489
488
bint is_ignore = errors== " ignore"
490
489
bint is_coerce = errors== " coerce"
491
490
bint is_same_offsets
492
491
_TSObject _ts
493
- int64_t value
494
- int out_local = 0 , out_tzoffset = 0
495
492
float tz_offset
496
493
set out_tzoffset_vals = set ()
497
- bint string_to_dts_failed
498
- datetime py_dt
499
494
tzinfo tz_out = None
500
495
bint found_tz = False , found_naive = False
501
496
cnp.broadcast mi
@@ -557,61 +552,40 @@ cpdef array_to_datetime(
557
552
# GH#32264 np.str_ object
558
553
val = str (val)
559
554
560
- if len (val) == 0 or val in nat_strings:
561
- iresult[i] = NPY_NAT
555
+ if parse_today_now(val, & iresult[i], utc):
556
+ # We can't _quite_ dispatch this to convert_str_to_tsobject
557
+ # bc there isn't a nice way to pass "utc"
562
558
cnp.PyArray_MultiIter_NEXT(mi)
563
559
continue
564
560
565
- string_to_dts_failed = string_to_dts(
566
- val, & dts, & out_bestunit, & out_local,
567
- & out_tzoffset, False , None , False
561
+ _ts = convert_str_to_tsobject(
562
+ val, None , unit = " ns" , dayfirst = dayfirst, yearfirst = yearfirst
568
563
)
569
- if string_to_dts_failed:
570
- # An error at this point is a _parsing_ error
571
- # specifically _not_ OutOfBoundsDatetime
572
- if parse_today_now(val, & iresult[i], utc):
573
- cnp.PyArray_MultiIter_NEXT(mi)
574
- continue
575
-
576
- py_dt = parse_datetime_string(val,
577
- dayfirst = dayfirst,
578
- yearfirst = yearfirst)
579
- # If the dateutil parser returned tzinfo, capture it
580
- # to check if all arguments have the same tzinfo
581
- tz = py_dt.utcoffset()
582
-
583
- if tz is not None :
584
- seen_datetime_offset = True
585
- # dateutil timezone objects cannot be hashed, so
586
- # store the UTC offsets in seconds instead
587
- out_tzoffset_vals.add(tz.total_seconds())
588
- else :
589
- # Add a marker for naive string, to track if we are
590
- # parsing mixed naive and aware strings
591
- out_tzoffset_vals.add(" naive" )
592
-
593
- _ts = convert_datetime_to_tsobject(py_dt, None )
594
- iresult[i] = _ts.value
564
+ try :
565
+ _ts.ensure_reso(NPY_FR_ns)
566
+ except OutOfBoundsDatetime as err:
567
+ # re-raise with better exception message
568
+ raise OutOfBoundsDatetime(
569
+ f" Out of bounds nanosecond timestamp: {val}"
570
+ ) from err
571
+
572
+ iresult[i] = _ts.value
573
+
574
+ tz = _ts.tzinfo
575
+ if tz is not None :
576
+ # dateutil timezone objects cannot be hashed, so
577
+ # store the UTC offsets in seconds instead
578
+ nsecs = tz.utcoffset(None ).total_seconds()
579
+ out_tzoffset_vals.add(nsecs)
580
+ # need to set seen_datetime_offset *after* the
581
+ # potentially-raising timezone(timedelta(...)) call,
582
+ # otherwise we can go down the is_same_offsets path
583
+ # bc len(out_tzoffset_vals) == 0
584
+ seen_datetime_offset = True
595
585
else :
596
- # No error reported by string_to_dts, pick back up
597
- # where we left off
598
- value = npy_datetimestruct_to_datetime(NPY_FR_ns, & dts)
599
- if out_local == 1 :
600
- seen_datetime_offset = True
601
- # Store the out_tzoffset in seconds
602
- # since we store the total_seconds of
603
- # dateutil.tz.tzoffset objects
604
- out_tzoffset_vals.add(out_tzoffset * 60. )
605
- tz = timezone(timedelta(minutes = out_tzoffset))
606
- value = tz_localize_to_utc_single(value, tz)
607
- out_local = 0
608
- out_tzoffset = 0
609
- else :
610
- # Add a marker for naive string, to track if we are
611
- # parsing mixed naive and aware strings
612
- out_tzoffset_vals.add(" naive" )
613
- iresult[i] = value
614
- check_dts_bounds(& dts)
586
+ # Add a marker for naive string, to track if we are
587
+ # parsing mixed naive and aware strings
588
+ out_tzoffset_vals.add(" naive" )
615
589
616
590
else :
617
591
raise TypeError (f" {type(val)} is not convertible to datetime" )
0 commit comments