Skip to content

Commit c50a9dc

Browse files
jbrockmendeljreback
authored andcommitted
perf improvements in tslibs.period (#21447)
1 parent 4918829 commit c50a9dc

File tree

3 files changed

+28
-9
lines changed

3 files changed

+28
-9
lines changed

pandas/_libs/src/util.pxd

+15
Original file line numberDiff line numberDiff line change
@@ -161,3 +161,18 @@ cdef inline bint _checknull(object val):
161161

162162
cdef inline bint is_period_object(object val):
163163
return getattr(val, '_typ', '_typ') == 'period'
164+
165+
166+
cdef inline bint is_offset_object(object val):
167+
"""
168+
Check if an object is a DateOffset object.
169+
170+
Parameters
171+
----------
172+
val : object
173+
174+
Returns
175+
-------
176+
is_date_offset : bool
177+
"""
178+
return getattr(val, '_typ', None) == "dateoffset"

pandas/_libs/tslib.pyx

+1-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ def ints_to_pydatetime(ndarray[int64_t] arr, tz=None, freq=None,
125125
elif box == "datetime":
126126
func_create = create_datetime_from_ts
127127
else:
128-
raise ValueError("box must be one of 'datetime', 'date', 'time' or" +
128+
raise ValueError("box must be one of 'datetime', 'date', 'time' or"
129129
" 'timestamp'")
130130

131131
if tz is not None:

pandas/_libs/tslibs/period.pyx

+12-8
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ from pandas.compat import PY2
1919

2020
cimport cython
2121

22-
from cpython.datetime cimport PyDateTime_Check, PyDateTime_IMPORT
22+
from cpython.datetime cimport (PyDateTime_Check, PyDelta_Check,
23+
PyDateTime_IMPORT)
2324
# import datetime C API
2425
PyDateTime_IMPORT
2526

@@ -1058,18 +1059,21 @@ cdef class _Period(object):
10581059
return hash((self.ordinal, self.freqstr))
10591060

10601061
def _add_delta(self, other):
1061-
if isinstance(other, (timedelta, np.timedelta64, offsets.Tick)):
1062+
cdef:
1063+
int64_t nanos, offset_nanos
1064+
1065+
if (PyDelta_Check(other) or util.is_timedelta64_object(other) or
1066+
isinstance(other, offsets.Tick)):
10621067
offset = frequencies.to_offset(self.freq.rule_code)
10631068
if isinstance(offset, offsets.Tick):
10641069
nanos = delta_to_nanoseconds(other)
10651070
offset_nanos = delta_to_nanoseconds(offset)
1066-
10671071
if nanos % offset_nanos == 0:
10681072
ordinal = self.ordinal + (nanos // offset_nanos)
10691073
return Period(ordinal=ordinal, freq=self.freq)
10701074
msg = 'Input cannot be converted to Period(freq={0})'
10711075
raise IncompatibleFrequency(msg.format(self.freqstr))
1072-
elif isinstance(other, offsets.DateOffset):
1076+
elif util.is_offset_object(other):
10731077
freqstr = other.rule_code
10741078
base = get_base_alias(freqstr)
10751079
if base == self.freq.rule_code:
@@ -1082,8 +1086,8 @@ cdef class _Period(object):
10821086

10831087
def __add__(self, other):
10841088
if is_period_object(self):
1085-
if isinstance(other, (timedelta, np.timedelta64,
1086-
offsets.DateOffset)):
1089+
if (PyDelta_Check(other) or util.is_timedelta64_object(other) or
1090+
util.is_offset_object(other)):
10871091
return self._add_delta(other)
10881092
elif other is NaT:
10891093
return NaT
@@ -1109,8 +1113,8 @@ cdef class _Period(object):
11091113

11101114
def __sub__(self, other):
11111115
if is_period_object(self):
1112-
if isinstance(other, (timedelta, np.timedelta64,
1113-
offsets.DateOffset)):
1116+
if (PyDelta_Check(other) or util.is_timedelta64_object(other) or
1117+
util.is_offset_object(other)):
11141118
neg_other = -other
11151119
return self + neg_other
11161120
elif util.is_integer_object(other):

0 commit comments

Comments
 (0)