Skip to content

PERF: use is_tick_offset to check for Tick #34032

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions pandas/_libs/tslibs/c_timestamp.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ from pandas._libs.tslibs.timezones cimport (
get_timezone, is_utc, tz_compare)
from pandas._libs.tslibs.timezones import UTC
from pandas._libs.tslibs.tzconversion cimport tz_convert_single
from pandas._libs.tslibs.offsets cimport is_tick_object


class NullFrequencyError(ValueError):
Expand Down Expand Up @@ -247,13 +248,9 @@ cdef class _Timestamp(datetime):
elif is_integer_object(other):
raise integer_op_not_supported(self)

elif PyDelta_Check(other) or hasattr(other, 'delta'):
# delta --> offsets.Tick
elif PyDelta_Check(other):
# logic copied from delta_to_nanoseconds to prevent circular import
if hasattr(other, 'nanos'):
# Tick
nanos = other.nanos
elif hasattr(other, 'delta'):
if hasattr(other, 'delta'):
# pd.Timedelta
nanos = other.value
elif PyDelta_Check(other):
Expand All @@ -264,6 +261,16 @@ cdef class _Timestamp(datetime):
result = type(self)(self.value + nanos, tz=self.tzinfo, freq=self.freq)
return result

elif is_tick_object(other):
try:
nanos = other.nanos
except OverflowError:
raise OverflowError(
f"the add operation between {other} and {self} will overflow"
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this has a from e?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

couldnt hurt, will add to the list

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kk

result = type(self)(self.value + nanos, tz=self.tzinfo, freq=self.freq)
return result

elif is_array(other):
if other.dtype.kind in ['i', 'u']:
raise integer_op_not_supported(self)
Expand All @@ -280,8 +287,7 @@ cdef class _Timestamp(datetime):
def __sub__(self, other):

if (is_timedelta64_object(other) or is_integer_object(other) or
PyDelta_Check(other) or hasattr(other, 'delta')):
# `delta` attribute is for offsets.Tick or offsets.Week obj
PyDelta_Check(other) or is_tick_object(other)):
neg_other = -other
return self + neg_other

Expand Down
6 changes: 2 additions & 4 deletions pandas/_libs/tslibs/nattype.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,7 @@ cdef class _NaT(datetime):
return c_NaT
elif util.is_datetime64_object(other) or util.is_timedelta64_object(other):
return c_NaT
elif hasattr(other, "delta"):
# Timedelta, offsets.Tick, offsets.Week
elif util.is_offset_object(other):
return c_NaT

elif util.is_integer_object(other) or util.is_period_object(other):
Expand Down Expand Up @@ -184,8 +183,7 @@ cdef class _NaT(datetime):
return c_NaT
elif util.is_datetime64_object(other) or util.is_timedelta64_object(other):
return c_NaT
elif hasattr(other, "delta"):
# offsets.Tick, offsets.Week
elif util.is_offset_object(other):
return c_NaT

elif util.is_integer_object(other) or util.is_period_object(other):
Expand Down
7 changes: 3 additions & 4 deletions pandas/_libs/tslibs/period.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,7 @@ from pandas._libs.tslibs.resolution import Resolution
from pandas._libs.tslibs.nattype import nat_strings
from pandas._libs.tslibs.nattype cimport (
_nat_scalar_rules, NPY_NAT, is_null_datetimelike, c_NaT as NaT)
from pandas._libs.tslibs.offsets cimport to_offset
from pandas._libs.tslibs.offsets import _Tick
from pandas._libs.tslibs.offsets cimport to_offset, is_tick_object
from pandas._libs.tslibs.tzconversion cimport tz_convert_utc_to_tzlocal


Expand Down Expand Up @@ -1588,9 +1587,9 @@ cdef class _Period:
int64_t nanos, offset_nanos

if (PyDelta_Check(other) or util.is_timedelta64_object(other) or
isinstance(other, _Tick)):
is_tick_object(other)):
offset = to_offset(self.freq.rule_code)
if isinstance(offset, _Tick):
if is_tick_object(offset):
nanos = delta_to_nanoseconds(other)
offset_nanos = delta_to_nanoseconds(offset)
if nanos % offset_nanos == 0:
Expand Down
26 changes: 11 additions & 15 deletions pandas/_libs/tslibs/timedeltas.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ from pandas._libs.tslibs.np_datetime cimport (
from pandas._libs.tslibs.nattype import nat_strings
from pandas._libs.tslibs.nattype cimport (
checknull_with_nat, NPY_NAT, c_NaT as NaT)
from pandas._libs.tslibs.offsets cimport to_offset
from pandas._libs.tslibs.offsets import _Tick as Tick
from pandas._libs.tslibs.offsets cimport to_offset, is_tick_object

# ----------------------------------------------------------------------
# Constants
Expand Down Expand Up @@ -140,10 +139,10 @@ def ints_to_pytimedelta(const int64_t[:] arr, box=False):
# ----------------------------------------------------------------------

cpdef int64_t delta_to_nanoseconds(delta) except? -1:
if hasattr(delta, 'nanos'):
if is_tick_object(delta):
return delta.nanos
if hasattr(delta, 'delta'):
delta = delta.delta
if isinstance(delta, _Timedelta):
delta = delta.value
if is_timedelta64_object(delta):
return delta.astype("timedelta64[ns]").item()
if is_integer_object(delta):
Expand Down Expand Up @@ -204,8 +203,8 @@ cdef convert_to_timedelta64(object ts, object unit):
else:
ts = parse_timedelta_string(ts)
ts = np.timedelta64(ts)
elif hasattr(ts, 'delta'):
ts = np.timedelta64(delta_to_nanoseconds(ts), 'ns')
elif is_tick_object(ts):
ts = np.timedelta64(ts.nanos, 'ns')

if PyDelta_Check(ts):
ts = np.timedelta64(delta_to_nanoseconds(ts), 'ns')
Expand Down Expand Up @@ -562,12 +561,10 @@ cdef bint _validate_ops_compat(other):
# return True if we are compat with operating
if checknull_with_nat(other):
return True
elif PyDelta_Check(other) or is_timedelta64_object(other):
elif is_any_td_scalar(other):
return True
elif isinstance(other, str):
return True
elif hasattr(other, 'delta'):
return True
return False


Expand Down Expand Up @@ -779,8 +776,7 @@ cdef class _Timedelta(timedelta):

if isinstance(other, _Timedelta):
ots = other
elif (is_timedelta64_object(other) or PyDelta_Check(other)
or isinstance(other, Tick)):
elif is_any_td_scalar(other):
ots = Timedelta(other)
# TODO: watch out for overflows

Expand Down Expand Up @@ -1249,8 +1245,8 @@ class Timedelta(_Timedelta):
if unit is not None:
value = value.astype(f'timedelta64[{unit}]')
value = value.astype('timedelta64[ns]')
elif hasattr(value, 'delta'):
value = np.timedelta64(delta_to_nanoseconds(value.delta), 'ns')
elif is_tick_object(value):
value = np.timedelta64(value.nanos, 'ns')
elif is_integer_object(value) or is_float_object(value):
# unit=None is de-facto 'ns'
unit = parse_timedelta_unit(unit)
Expand Down Expand Up @@ -1460,7 +1456,7 @@ class Timedelta(_Timedelta):

cdef bint is_any_td_scalar(object obj):
return (
PyDelta_Check(obj) or is_timedelta64_object(obj) or isinstance(obj, Tick)
PyDelta_Check(obj) or is_timedelta64_object(obj) or is_tick_object(obj)
)


Expand Down