Skip to content

Commit

Permalink
move _add__ and __sub__ to liboffsets, implement _Tick (#21694)
Browse files Browse the repository at this point in the history
  • Loading branch information
jbrockmendel authored and jreback committed Jul 3, 2018
1 parent 1de57da commit a70e356
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 27 deletions.
31 changes: 29 additions & 2 deletions pandas/_libs/tslibs/offsets.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -368,12 +368,31 @@ class _BaseOffset(object):
if name not in ['n', 'normalize']}
return {name: kwds[name] for name in kwds if kwds[name] is not None}

def __add__(self, other):
if getattr(other, "_typ", None) in ["datetimeindex",
"series", "period"]:
# defer to the other class's implementation
return other + self
try:
return self.apply(other)
except ApplyTypeError:
return NotImplemented

def __sub__(self, other):
if isinstance(other, datetime):
raise TypeError('Cannot subtract datetime from offset.')
elif type(other) == type(self):
return type(self)(self.n - other.n, normalize=self.normalize,
**self.kwds)
else: # pragma: no cover
return NotImplemented

def __call__(self, other):
return self.apply(other)

def __mul__(self, other):
return self.__class__(n=other * self.n, normalize=self.normalize,
**self.kwds)
return type(self)(n=other * self.n, normalize=self.normalize,
**self.kwds)

def __neg__(self):
# Note: we are defering directly to __mul__ instead of __rmul__, as
Expand Down Expand Up @@ -495,6 +514,14 @@ class BaseOffset(_BaseOffset):
return -self + other


class _Tick(object):
"""
dummy class to mix into tseries.offsets.Tick so that in tslibs.period we
can do isinstance checks on _Tick and avoid importing tseries.offsets
"""
pass


# ----------------------------------------------------------------------
# RelativeDelta Arithmetic

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 @@ -52,8 +52,7 @@ from resolution import Resolution
from nattype import nat_strings, NaT, iNaT
from nattype cimport _nat_scalar_rules, NPY_NAT, is_null_datetimelike
from offsets cimport to_offset

from pandas.tseries import offsets
from offsets import _Tick

cdef bint PY2 = str == bytes

Expand Down Expand Up @@ -1060,9 +1059,9 @@ cdef class _Period(object):
int64_t nanos, offset_nanos

if (PyDelta_Check(other) or util.is_timedelta64_object(other) or
isinstance(other, offsets.Tick)):
isinstance(other, _Tick)):
offset = to_offset(self.freq.rule_code)
if isinstance(offset, offsets.Tick):
if isinstance(offset, _Tick):
nanos = delta_to_nanoseconds(other)
offset_nanos = delta_to_nanoseconds(offset)
if nanos % offset_nanos == 0:
Expand Down
23 changes: 2 additions & 21 deletions pandas/tseries/offsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from pandas import compat
import numpy as np

from pandas.core.dtypes.generic import ABCSeries, ABCDatetimeIndex, ABCPeriod
from pandas.core.dtypes.generic import ABCPeriod
from pandas.core.tools.datetimes import to_datetime
import pandas.core.common as com

Expand Down Expand Up @@ -288,25 +288,6 @@ def _repr_attrs(self):
def name(self):
return self.rule_code

def __add__(self, other):
if isinstance(other, (ABCDatetimeIndex, ABCSeries)):
return other + self
elif isinstance(other, ABCPeriod):
return other + self
try:
return self.apply(other)
except ApplyTypeError:
return NotImplemented

def __sub__(self, other):
if isinstance(other, datetime):
raise TypeError('Cannot subtract datetime from offset.')
elif type(other) == type(self):
return self.__class__(self.n - other.n, normalize=self.normalize,
**self.kwds)
else: # pragma: no cover
return NotImplemented

def rollback(self, dt):
"""Roll provided date backward to next offset only if not on offset"""
dt = as_timestamp(dt)
Expand Down Expand Up @@ -2106,7 +2087,7 @@ def f(self, other):
return f


class Tick(SingleConstructorOffset):
class Tick(liboffsets._Tick, SingleConstructorOffset):
_inc = Timedelta(microseconds=1000)
_prefix = 'undefined'
_attributes = frozenset(['n', 'normalize'])
Expand Down

0 comments on commit a70e356

Please sign in to comment.