Skip to content

Commit 493ef8f

Browse files
jbrockmendelyehoshuadimarsky
authored andcommitted
REF: expose pandas_timedelta_to_timedeltastruct (pandas-dev#46578)
* REF: expose pandas_timedelta_to_timedeltastruct * mypy fixup
1 parent 17cb27e commit 493ef8f

File tree

6 files changed

+48
-22
lines changed

6 files changed

+48
-22
lines changed

pandas/_libs/tslibs/__init__.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,18 @@
2727
]
2828

2929
from pandas._libs.tslibs import dtypes
30-
from pandas._libs.tslibs.conversion import (
31-
OutOfBoundsTimedelta,
32-
localize_pydatetime,
33-
)
30+
from pandas._libs.tslibs.conversion import localize_pydatetime
3431
from pandas._libs.tslibs.dtypes import Resolution
3532
from pandas._libs.tslibs.nattype import (
3633
NaT,
3734
NaTType,
3835
iNaT,
3936
nat_strings,
4037
)
41-
from pandas._libs.tslibs.np_datetime import OutOfBoundsDatetime
38+
from pandas._libs.tslibs.np_datetime import (
39+
OutOfBoundsDatetime,
40+
OutOfBoundsTimedelta,
41+
)
4242
from pandas._libs.tslibs.offsets import (
4343
BaseOffset,
4444
Tick,

pandas/_libs/tslibs/conversion.pyx

+4-10
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@ from pandas._libs.tslibs.np_datetime cimport (
4444
pydatetime_to_dt64,
4545
)
4646

47-
from pandas._libs.tslibs.np_datetime import OutOfBoundsDatetime
47+
from pandas._libs.tslibs.np_datetime import (
48+
OutOfBoundsDatetime,
49+
OutOfBoundsTimedelta,
50+
)
4851

4952
from pandas._libs.tslibs.timezones cimport (
5053
get_dst_info,
@@ -85,15 +88,6 @@ DT64NS_DTYPE = np.dtype('M8[ns]')
8588
TD64NS_DTYPE = np.dtype('m8[ns]')
8689

8790

88-
class OutOfBoundsTimedelta(ValueError):
89-
"""
90-
Raised when encountering a timedelta value that cannot be represented
91-
as a timedelta64[ns].
92-
"""
93-
# Timedelta analogue to OutOfBoundsDatetime
94-
pass
95-
96-
9791
# ----------------------------------------------------------------------
9892
# Unit Conversion Helpers
9993

pandas/_libs/tslibs/np_datetime.pxd

+6
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ cdef extern from "src/datetime/np_datetime.h":
6666
npy_datetime npy_datetimestruct_to_datetime(NPY_DATETIMEUNIT fr,
6767
npy_datetimestruct *d) nogil
6868

69+
void pandas_timedelta_to_timedeltastruct(npy_timedelta val,
70+
NPY_DATETIMEUNIT fr,
71+
pandas_timedeltastruct *result
72+
) nogil
6973

7074
cdef bint cmp_scalar(int64_t lhs, int64_t rhs, int op) except -1
7175

@@ -94,3 +98,5 @@ cpdef cnp.ndarray astype_overflowsafe(
9498
cnp.dtype dtype, # ndarray[datetime64[anyunit]]
9599
bint copy=*,
96100
)
101+
102+
cdef bint cmp_dtstructs(npy_datetimestruct* left, npy_datetimestruct* right, int op)

pandas/_libs/tslibs/np_datetime.pyi

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import numpy as np
22

33
class OutOfBoundsDatetime(ValueError): ...
4+
class OutOfBoundsTimedelta(ValueError): ...
45

56
# only exposed for testing
67
def py_get_unit_from_dtype(dtype: np.dtype): ...

pandas/_libs/tslibs/np_datetime.pyx

+31-5
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,6 @@ cdef extern from "src/datetime/np_datetime.h":
3434
int cmp_npy_datetimestruct(npy_datetimestruct *a,
3535
npy_datetimestruct *b)
3636

37-
void pandas_timedelta_to_timedeltastruct(npy_timedelta val,
38-
NPY_DATETIMEUNIT fr,
39-
pandas_timedeltastruct *result
40-
) nogil
41-
4237
# AS, FS, PS versions exist but are not imported because they are not used.
4338
npy_datetimestruct _NS_MIN_DTS, _NS_MAX_DTS
4439
npy_datetimestruct _US_MIN_DTS, _US_MAX_DTS
@@ -100,6 +95,28 @@ def py_get_unit_from_dtype(dtype):
10095
# Comparison
10196

10297

98+
cdef bint cmp_dtstructs(
99+
npy_datetimestruct* left, npy_datetimestruct* right, int op
100+
):
101+
cdef:
102+
int cmp_res
103+
104+
cmp_res = cmp_npy_datetimestruct(left, right)
105+
if op == Py_EQ:
106+
return cmp_res == 0
107+
if op == Py_NE:
108+
return cmp_res != 0
109+
if op == Py_GT:
110+
return cmp_res == 1
111+
if op == Py_LT:
112+
return cmp_res == -1
113+
if op == Py_GE:
114+
return cmp_res == 1 or cmp_res == 0
115+
else:
116+
# i.e. op == Py_LE
117+
return cmp_res == -1 or cmp_res == 0
118+
119+
103120
cdef inline bint cmp_scalar(int64_t lhs, int64_t rhs, int op) except -1:
104121
"""
105122
cmp_scalar is a more performant version of PyObject_RichCompare
@@ -127,6 +144,15 @@ class OutOfBoundsDatetime(ValueError):
127144
pass
128145

129146

147+
class OutOfBoundsTimedelta(ValueError):
148+
"""
149+
Raised when encountering a timedelta value that cannot be represented
150+
as a timedelta64[ns].
151+
"""
152+
# Timedelta analogue to OutOfBoundsDatetime
153+
pass
154+
155+
130156
cdef check_dts_bounds(npy_datetimestruct *dts, NPY_DATETIMEUNIT unit=NPY_FR_ns):
131157
"""Raises OutOfBoundsDatetime if the given date is outside the range that
132158
can be represented by nanosecond-resolution 64-bit integers."""

pandas/_libs/tslibs/timedeltas.pyx

+1-2
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ from pandas._libs.tslibs.np_datetime cimport (
5151
pandas_timedeltastruct,
5252
td64_to_tdstruct,
5353
)
54+
from pandas._libs.tslibs.np_datetime import OutOfBoundsTimedelta
5455
from pandas._libs.tslibs.offsets cimport is_tick_object
5556
from pandas._libs.tslibs.util cimport (
5657
is_array,
@@ -188,7 +189,6 @@ cpdef int64_t delta_to_nanoseconds(delta) except? -1:
188189
+ delta.microseconds
189190
) * 1000
190191
except OverflowError as err:
191-
from pandas._libs.tslibs.conversion import OutOfBoundsTimedelta
192192
raise OutOfBoundsTimedelta(*err.args) from err
193193

194194
raise TypeError(type(delta))
@@ -226,7 +226,6 @@ cdef object ensure_td64ns(object ts):
226226
# NB: cython#1381 this cannot be *=
227227
td64_value = td64_value * mult
228228
except OverflowError as err:
229-
from pandas._libs.tslibs.conversion import OutOfBoundsTimedelta
230229
raise OutOfBoundsTimedelta(ts) from err
231230

232231
return np.timedelta64(td64_value, "ns")

0 commit comments

Comments
 (0)