@@ -308,6 +308,21 @@ cdef convert_to_timedelta64(object ts, str unit):
308
308
return ts.astype(" timedelta64[ns]" )
309
309
310
310
311
+ cpdef to_timedelta64(object value, str unit):
312
+ """
313
+ Wrapper around convert_to_timedelta64() that does overflow checks.
314
+ TODO: also construct non-nano
315
+ TODO: do all overflow-unsafe operations here
316
+ TODO: constrain unit to a more specific type
317
+ """
318
+ with cython.overflowcheck(True ):
319
+ try :
320
+ return convert_to_timedelta64(value, unit)
321
+ except OverflowError as ex:
322
+ msg = f" {value} outside allowed range [{TIMEDELTA_MIN_NS}ns, {TIMEDELTA_MAX_NS}ns]"
323
+ raise OutOfBoundsTimedelta(msg) from ex
324
+
325
+
311
326
@ cython.boundscheck (False )
312
327
@ cython.wraparound (False )
313
328
def array_to_timedelta64 (
@@ -1473,49 +1488,44 @@ class Timedelta(_Timedelta):
1473
1488
)
1474
1489
if isinstance (value, str ) and unit is not None :
1475
1490
raise ValueError (" unit must not be specified if the value is a str" )
1476
- elif value is _no_input:
1477
- if not kwargs:
1478
- raise ValueError (
1479
- " cannot construct a Timedelta without a value/unit "
1480
- " or descriptive keywords (days,seconds....)"
1481
- )
1482
- if not kwargs.keys() <= set (cls ._allowed_kwargs):
1483
- raise ValueError (
1484
- " cannot construct a Timedelta from the passed arguments, "
1485
- f" allowed keywords are {cls._allowed_kwargs}"
1486
- )
1491
+ elif value is _no_input and not kwargs:
1492
+ raise ValueError (
1493
+ " cannot construct a Timedelta without a value/unit "
1494
+ " or descriptive keywords (days,seconds....)"
1495
+ )
1496
+ if not kwargs.keys() <= set (cls ._allowed_kwargs):
1497
+ raise ValueError (
1498
+ " cannot construct a Timedelta from the passed arguments, "
1499
+ f" allowed keywords are {cls._allowed_kwargs}"
1500
+ )
1487
1501
1488
- try :
1489
- # GH43764, convert any input to nanoseconds first, to ensure any potential
1490
- # nanosecond contributions from kwargs parsed as floats are included
1491
- kwargs = collections.defaultdict(int , {key: _to_py_int_float(val) for key, val in kwargs.items()})
1492
- if kwargs:
1493
- value = convert_to_timedelta64(
1494
- sum ((
1495
- kwargs[" weeks" ] * 7 * 24 * 3600 * 1 _000_000_000,
1496
- kwargs[" days" ] * 24 * 3600 * 1 _000_000_000,
1497
- kwargs[" hours" ] * 3600 * 1 _000_000_000,
1498
- kwargs[" minutes" ] * 60 * 1 _000_000_000,
1499
- kwargs[" seconds" ] * 1 _000_000_000,
1500
- kwargs[" milliseconds" ] * 1 _000_000,
1501
- kwargs[" microseconds" ] * 1 _000,
1502
- kwargs[" nanoseconds" ],
1503
- )),
1504
- " ns" ,
1505
- )
1506
- else :
1507
- if is_integer_object(value) or is_float_object(value):
1508
- unit = parse_timedelta_unit(unit)
1509
- else :
1510
- unit = " ns"
1511
- value = convert_to_timedelta64(value, unit)
1512
- except OverflowError as ex:
1513
- msg = f" outside allowed range [{TIMEDELTA_MIN_NS}ns, {TIMEDELTA_MAX_NS}ns]"
1514
- raise OutOfBoundsTimedelta(msg) from ex
1502
+ # GH43764, convert any input to nanoseconds first, to ensure any potential
1503
+ # nanosecond contributions from kwargs parsed as floats are included
1504
+ kwargs = collections.defaultdict(int , {key: _to_py_int_float(val) for key, val in kwargs.items()})
1505
+ if kwargs:
1506
+ value = to_timedelta64(
1507
+ sum ((
1508
+ kwargs[" weeks" ] * 7 * 24 * 3600 * 1 _000_000_000,
1509
+ kwargs[" days" ] * 24 * 3600 * 1 _000_000_000,
1510
+ kwargs[" hours" ] * 3600 * 1 _000_000_000,
1511
+ kwargs[" minutes" ] * 60 * 1 _000_000_000,
1512
+ kwargs[" seconds" ] * 1 _000_000_000,
1513
+ kwargs[" milliseconds" ] * 1 _000_000,
1514
+ kwargs[" microseconds" ] * 1 _000,
1515
+ kwargs[" nanoseconds" ],
1516
+ )),
1517
+ " ns" ,
1518
+ )
1515
1519
else :
1516
- if is_td64nat(value):
1517
- return NaT
1518
- return _timedelta_from_value_and_reso(value.view(" i8" ), NPY_FR_ns)
1520
+ if is_integer_object(value) or is_float_object(value):
1521
+ unit = parse_timedelta_unit(unit)
1522
+ else :
1523
+ unit = " ns"
1524
+ value = to_timedelta64(value, unit)
1525
+
1526
+ if is_td64nat(value):
1527
+ return NaT
1528
+ return _timedelta_from_value_and_reso(value.view(" i8" ), NPY_FR_ns)
1519
1529
1520
1530
def __setstate__ (self , state ):
1521
1531
if len (state) == 1 :
0 commit comments