Skip to content

Commit 16d14ab

Browse files
committed
ENH: Fix out-of-bounds error handling in _to_datetime_with_unit
1 parent 510951b commit 16d14ab

File tree

1 file changed

+29
-10
lines changed

1 file changed

+29
-10
lines changed

pandas/core/tools/datetimes.py

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@
7575
from pandas.core.construction import extract_array
7676
from pandas.core.indexes.base import Index
7777
from pandas.core.indexes.datetimes import DatetimeIndex
78-
7978
if TYPE_CHECKING:
8079
from collections.abc import (
8180
Callable,
@@ -479,49 +478,70 @@ def _array_strptime_with_fallback(
479478
return Index(result, dtype=result.dtype, name=name)
480479

481480

482-
def _to_datetime_with_unit(arg, unit, name, utc: bool, errors: str) -> Index:
481+
482+
483+
484+
def _to_datetime_with_unit(arg, unit, name, utc: bool, errors: str) -> DatetimeIndex:
483485
"""
484-
to_datetime specalized to the case where a 'unit' is passed.
486+
to_datetime specialized to the case where a 'unit' is passed.
487+
Fixes a bug where scalar out-of-bounds values were not raising
488+
an error consistently.
485489
"""
490+
# Ensure we handle both array-likes and scalars the same way.
491+
# extract_array can return a scalar if 'arg' is scalar-like;
492+
# so we force everything into at least 1D shape.
486493
arg = extract_array(arg, extract_numpy=True)
494+
arg = np.atleast_1d(arg)
487495

488496
# GH#30050 pass an ndarray to tslib.array_to_datetime
489497
# because it expects an ndarray argument
490498
if isinstance(arg, IntegerArray):
499+
# For IntegerArray, we can directly convert
491500
arr = arg.astype(f"datetime64[{unit}]")
492501
tz_parsed = None
502+
493503
else:
504+
# Now we have a guaranteed ndarray
494505
arg = np.asarray(arg)
495506

496507
if arg.dtype.kind in "iu":
497508
# Note we can't do "f" here because that could induce unwanted
498-
# rounding GH#14156, GH#20445
509+
# rounding GH#14156, GH#20445
499510
arr = arg.astype(f"datetime64[{unit}]", copy=False)
500511
try:
501512
arr = astype_overflowsafe(arr, np.dtype("M8[ns]"), copy=False)
502513
except OutOfBoundsDatetime:
503514
if errors == "raise":
504515
raise
516+
# errors != "raise" => coerce to object and retry
505517
arg = arg.astype(object)
506518
return _to_datetime_with_unit(arg, unit, name, utc, errors)
507519
tz_parsed = None
508520

509521
elif arg.dtype.kind == "f":
522+
# Floating dtypes
510523
with np.errstate(over="raise"):
511524
try:
512525
arr = cast_from_unit_vectorized(arg, unit=unit)
513526
except OutOfBoundsDatetime as err:
514527
if errors != "raise":
528+
# coerce to object and retry
515529
return _to_datetime_with_unit(
516-
arg.astype(object), unit, name, utc, errors
530+
arg.astype(object),
531+
unit,
532+
name,
533+
utc,
534+
errors,
517535
)
518536
raise OutOfBoundsDatetime(
519537
f"cannot convert input with unit '{unit}'"
520538
) from err
521539

522540
arr = arr.view("M8[ns]")
523541
tz_parsed = None
542+
524543
else:
544+
# Fallback: treat as object dtype
525545
arg = arg.astype(object, copy=False)
526546
arr, tz_parsed = tslib.array_to_datetime(
527547
arg,
@@ -531,23 +551,22 @@ def _to_datetime_with_unit(arg, unit, name, utc: bool, errors: str) -> Index:
531551
creso=NpyDatetimeUnit.NPY_FR_ns.value,
532552
)
533553

554+
# Construct a DatetimeIndex from the array
534555
result = DatetimeIndex(arr, name=name)
535-
if not isinstance(result, DatetimeIndex):
536-
return result
537556

538-
# GH#23758: We may still need to localize the result with tz
539-
# GH#25546: Apply tz_parsed first (from arg), then tz (from caller)
540-
# result will be naive but in UTC
557+
# May need to localize result to parsed tz or convert to UTC if requested
541558
result = result.tz_localize("UTC").tz_convert(tz_parsed)
542559

543560
if utc:
544561
if result.tz is None:
545562
result = result.tz_localize("utc")
546563
else:
547564
result = result.tz_convert("utc")
565+
548566
return result
549567

550568

569+
551570
def _adjust_to_origin(arg, origin, unit):
552571
"""
553572
Helper function for to_datetime.

0 commit comments

Comments
 (0)