@@ -308,6 +308,21 @@ cdef convert_to_timedelta64(object ts, str unit):
308308 return ts.astype(" timedelta64[ns]" )
309309
310310
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+
311326@ cython.boundscheck (False )
312327@ cython.wraparound (False )
313328def array_to_timedelta64 (
@@ -1473,49 +1488,44 @@ class Timedelta(_Timedelta):
14731488 )
14741489 if isinstance (value, str ) and unit is not None :
14751490 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+ )
14871501
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+ )
15151519 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)
15191529
15201530 def __setstate__ (self , state ):
15211531 if len (state) == 1 :
0 commit comments