Skip to content
15 changes: 15 additions & 0 deletions pandas/_libs/src/util.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,18 @@ cdef inline bint _checknull(object val):

cdef inline bint is_period_object(object val):
return getattr(val, '_typ', '_typ') == 'period'


cdef inline bint is_offset_object(object val):
"""
Check if an object is a DateOffset object.

Parameters
----------
val : object

Returns
-------
is_date_offset : bool
"""
return getattr(val, '_typ', None) == "dateoffset"
2 changes: 1 addition & 1 deletion pandas/_libs/tslib.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ def ints_to_pydatetime(ndarray[int64_t] arr, tz=None, freq=None,
elif box == "datetime":
func_create = create_datetime_from_ts
else:
raise ValueError("box must be one of 'datetime', 'date', 'time' or" +
raise ValueError("box must be one of 'datetime', 'date', 'time' or"
" 'timestamp'")

if tz is not None:
Expand Down
20 changes: 12 additions & 8 deletions pandas/_libs/tslibs/period.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ from pandas.compat import PY2

cimport cython

from cpython.datetime cimport PyDateTime_Check, PyDateTime_IMPORT
from cpython.datetime cimport (PyDateTime_Check, PyDelta_Check,
PyDateTime_IMPORT)
# import datetime C API
PyDateTime_IMPORT

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

def _add_delta(self, other):
if isinstance(other, (timedelta, np.timedelta64, offsets.Tick)):
cdef:
int64_t nanos, offset_nanos

if (PyDelta_Check(other) or util.is_timedelta64_object(other) or
isinstance(other, offsets.Tick)):
offset = frequencies.to_offset(self.freq.rule_code)
if isinstance(offset, offsets.Tick):
nanos = delta_to_nanoseconds(other)
offset_nanos = delta_to_nanoseconds(offset)

if nanos % offset_nanos == 0:
ordinal = self.ordinal + (nanos // offset_nanos)
return Period(ordinal=ordinal, freq=self.freq)
msg = 'Input cannot be converted to Period(freq={0})'
raise IncompatibleFrequency(msg.format(self.freqstr))
elif isinstance(other, offsets.DateOffset):
elif util.is_offset_object(other):
freqstr = other.rule_code
base = get_base_alias(freqstr)
if base == self.freq.rule_code:
Expand All @@ -1082,8 +1086,8 @@ cdef class _Period(object):

def __add__(self, other):
if is_period_object(self):
if isinstance(other, (timedelta, np.timedelta64,
offsets.DateOffset)):
if (PyDelta_Check(other) or util.is_timedelta64_object(other) or
util.is_offset_object(other)):
return self._add_delta(other)
elif other is NaT:
return NaT
Expand All @@ -1109,8 +1113,8 @@ cdef class _Period(object):

def __sub__(self, other):
if is_period_object(self):
if isinstance(other, (timedelta, np.timedelta64,
offsets.DateOffset)):
if (PyDelta_Check(other) or util.is_timedelta64_object(other) or
util.is_offset_object(other)):
neg_other = -other
return self + neg_other
elif util.is_integer_object(other):
Expand Down