Skip to content

move _add__ and __sub__ to liboffsets, implement _Tick #21694

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 7 commits into from
Jul 3, 2018
Merged
Show file tree
Hide file tree
Changes from 5 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
27 changes: 27 additions & 0 deletions pandas/_libs/tslibs/offsets.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,25 @@ 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 self.__class__(self.n - other.n, normalize=self.normalize,
Copy link
Contributor

Choose a reason for hiding this comment

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

can you change to use type(self) here, I don't think we use the long form anywhere.

Copy link
Member Author

Choose a reason for hiding this comment

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

its used below in __mul__. change it there too while I'm at it?

Copy link
Contributor

Choose a reason for hiding this comment

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

yeah might as well, its a bit more clean.

**self.kwds)
else: # pragma: no cover
return NotImplemented

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

Expand Down Expand Up @@ -491,6 +510,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 @@ -54,8 +54,7 @@ from resolution import Resolution
from nattype import nat_strings, NaT, iNaT
from nattype cimport _nat_scalar_rules, NPY_NAT
from offsets cimport to_offset

from pandas.tseries import offsets
from offsets import _Tick

cdef bint PY2 = str == bytes

Expand Down Expand Up @@ -1062,9 +1061,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 @@ -311,25 +311,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 @@ -2129,7 +2110,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