@@ -201,28 +201,76 @@ def ints_to_pytimedelta(ndarray m8values, box=False):
201
201
202
202
# ----------------------------------------------------------------------
203
203
204
- cpdef int64_t delta_to_nanoseconds(delta) except ? - 1 :
205
- if is_tick_object(delta):
206
- return delta.nanos
207
- if isinstance (delta, _Timedelta):
208
- if delta._reso == NPY_FR_ns:
209
- return delta.value
210
- raise NotImplementedError (delta._reso)
211
204
212
- if is_timedelta64_object(delta):
213
- return get_timedelta64_value(ensure_td64ns(delta))
205
+ cpdef int64_t delta_to_nanoseconds(
206
+ delta,
207
+ NPY_DATETIMEUNIT reso = NPY_FR_ns,
208
+ bint round_ok = True ,
209
+ bint allow_year_month = False ,
210
+ ) except ? - 1 :
211
+ cdef:
212
+ _Timedelta td
213
+ NPY_DATETIMEUNIT in_reso
214
+ int64_t n
215
+
216
+ if is_tick_object(delta):
217
+ n = delta.n
218
+ in_reso = delta._reso
219
+ if in_reso == reso:
220
+ return n
221
+ else :
222
+ td = Timedelta._from_value_and_reso(delta.n, reso = in_reso)
223
+
224
+ elif isinstance (delta, _Timedelta):
225
+ td = delta
226
+ n = delta.value
227
+ in_reso = delta._reso
228
+ if in_reso == reso:
229
+ return n
230
+
231
+ elif is_timedelta64_object(delta):
232
+ in_reso = get_datetime64_unit(delta)
233
+ n = get_timedelta64_value(delta)
234
+ if in_reso == reso:
235
+ return n
236
+ else :
237
+ # _from_value_and_reso does not support Year, Month, or unit-less,
238
+ # so we have special handling if speciifed
239
+ try :
240
+ td = Timedelta._from_value_and_reso(n, reso = in_reso)
241
+ except NotImplementedError :
242
+ if allow_year_month:
243
+ td64 = ensure_td64ns(delta)
244
+ return delta_to_nanoseconds(td64, reso = reso)
245
+ else :
246
+ raise
214
247
215
- if PyDelta_Check(delta):
248
+ elif PyDelta_Check(delta):
249
+ in_reso = NPY_DATETIMEUNIT.NPY_FR_us
216
250
try :
217
- return (
251
+ n = (
218
252
delta.days * 24 * 3600 * 1 _000_000
219
253
+ delta.seconds * 1 _000_000
220
254
+ delta.microseconds
221
- ) * 1000
255
+ )
222
256
except OverflowError as err:
223
257
raise OutOfBoundsTimedelta(* err.args) from err
224
258
225
- raise TypeError (type (delta))
259
+ if in_reso == reso:
260
+ return n
261
+ else :
262
+ td = Timedelta._from_value_and_reso(n, reso = in_reso)
263
+
264
+ else :
265
+ raise TypeError (type (delta))
266
+
267
+ try :
268
+ return td._as_reso(reso, round_ok = round_ok).value
269
+ except OverflowError as err:
270
+ unit_str = npy_unit_to_abbrev(reso)
271
+ raise OutOfBoundsTimedelta(
272
+ f" Cannot cast {str(delta)} to unit={unit_str} without overflow."
273
+ ) from err
226
274
227
275
228
276
@ cython.overflowcheck (True )
@@ -1411,6 +1459,7 @@ cdef class _Timedelta(timedelta):
1411
1459
else :
1412
1460
mult = get_conversion_factor(self ._reso, reso)
1413
1461
with cython.overflowcheck(True ):
1462
+ # Note: caller is responsible for re-raising as OutOfBoundsTimedelta
1414
1463
value = self .value * mult
1415
1464
return type (self )._from_value_and_reso(value, reso = reso)
1416
1465
0 commit comments