8000 REF: De-duplicate pieces of datetimelike arithmetic by jbrockmendel · Pull Request #23166 · pandas-dev/pandas · GitHub
[go: up one dir, main page]

Skip to content

REF: De-duplicate pieces of datetimelike arithmetic #23166

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

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
implement semi_shallow_copy, de-duplicate add_delta
  • Loading branch information
jbrockmendel committed Oct 15, 2018
commit 6ed0694599f87de1833d3d4aab4e24bba1aa9df7
48 changes: 43 additions & 5 deletions pandas/core/arrays/datetimelike.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,15 @@ def _shallow_copy(self, values=None, **kwargs):
attributes['dtype'] = self.dtype
return self._simple_new(values, **attributes)

def _semi_shallow_copy(self, values):
# similar to shallow_copy, but with freq="infer"
if is_period_dtype(self):
return self._shallow_copy(values)
elif is_timedelta64_dtype(self):
return type(self)(values, freq='infer')
else:
8000 return type(self)(values, tz=self.tz, freq="infer")


class DatetimeLikeArrayMixin(ExtensionOpsMixin, AttributesMixin):
"""
Expand Down Expand Up @@ -339,8 +348,38 @@ def _sub_period(self, other):
def _add_offset(self, offset):
raise com.AbstractMethodError(self)

def _add_delta(self, other):
raise com.AbstractMethodError(self)
def _add_delta(self, delta):
"""
Add a timedelta-like, DateOffset, or TimedeltaIndex-like object
to self.

Parameters
----------
delta : {timedelta, np.timedelta64, DateOffset,
TimedeltaIndex, ndarray[timedelta64]}

Returns
-------
result : same type as self

Notes
-----
The result's name is set outside of _add_delta by the calling
method (__add__ or __sub__)
"""
if is_period_dtype(self) and not isinstance(self.freq, Tick):
# We cannot add timedelta-like to non-tick PeriodArray
raise IncompatibleFrequency("Input has different freq from "
"{cls}(freq={freqstr})"
.format(cls=type(self).__name__,
freqstr=self.freqstr))

if isinstance(delta, (Tick, timedelta, np.timedelta64)):
new_values = self._add_delta_td(delta)
elif is_timedelta64_dtype(delta):
new_values = self._add_delta_tdi(delta)

return self._semi_shallow_copy(new_values)

def _add_delta_td(self, other):
"""
Expand All @@ -350,8 +389,7 @@ def _add_delta_td(self, other):
inc = delta_to_nanoseconds(other)
new_values = checked_add_with_arr(self.asi8, inc,
arr_mask=self._isnan).view('i8')
if self.hasnans:
new_values[self._isnan] = iNaT
new_values = self._maybe_mask_results(new_values, fill_value=iNaT)
return new_values.view('i8')

def _add_delta_tdi(self, other):
Expand Down Expand Up @@ -462,7 +500,7 @@ def _addsub_int_array(self, other, op):
res_values = checked_add_with_arr(self.asi8, other,
arr_mask=self._isnan)
res_values = res_values.view('i8')
res_values[self._isnan] = iNaT
res_values = self._maybe_mask_results(res_values, fill_value=iNaT)
return self._from_ordinals(res_values, freq=self.freq)

elif self.freq is None:
Expand Down
26 changes: 0 additions & 26 deletions pandas/core/arrays/datetimes.py
Original file line number Diff line number Diff line change
Expand Up @@ -487,32 +487,6 @@ def _sub_datelike(self, other):
fill_value=iNaT)
return result.view('timedelta64[ns]')

def _add_delta(self, delta):
"""
Add a timedelta-like, DateOffset, or TimedeltaIndex-like object
to self.

Parameters
----------
delta : {timedelta, np.timedelta64, DateOffset,
TimedeltaIndex, ndarray[timedelta64]}

Returns
-------
result : same type as self

Notes
-----
The result's name is set outside of _add_delta by the calling
method (__add__ or __sub__)
"""
if isinstance(delta, (Tick, timedelta, np.timedelta64)):
new_values = self._add_delta_td(delta)
elif is_timedelta64_dtype(delta):
new_values = self._add_delta_tdi(delta)

return type(self)(new_values, tz=self.tz, freq='infer')

# -----------------------------------------------------------------
# Timezone Conversion and Localization Methods

Expand Down
31 changes: 0 additions & 31 deletions pandas/core/arrays/period.py
Original file line number Diff line number Diff line change
Expand Up @@ -378,37 +378,6 @@ def _add_delta_tdi(self, other):
delta = self._check_timedeltalike_freq_compat(other)
return self._addsub_int_array(delta, operator.add)

def _add_delta(self, other):
"""
Add a timedelta-like, Tick, or TimedeltaIndex-like object
to self.

Parameters
----------
other : {timedelta, np.timedelta64, Tick,
TimedeltaIndex, ndarray[timedelta64]}

Returns
-------
result : same type as self
"""
if not isinstance(self.freq, Tick):
# We cannot add timedelta-like to non-tick PeriodArray
raise IncompatibleFrequency("Input has different freq from "
"{cls}(freq={freqstr})"
.format(cls=type(self).__name__,
freqstr=self.freqstr))

# TODO: standardize across datetimelike subclasses whether to return
# i8 view or _shallow_copy
if isinstance(other, (Tick, timedelta, np.timedelta64)):
new_values = self._add_delta_td(other)
elif is_timedelta64_dtype(other):
# ndarray[timedelta64] or TimedeltaArray/index
new_values = self._add_delta_tdi(other)

return self._shallow_copy(new_values)

@deprecate_kwarg(old_arg_name='n', new_arg_name='periods')
def shift(self, periods):
"""
Expand Down
26 changes: 0 additions & 26 deletions pandas/core/arrays/timedeltas.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,32 +196,6 @@ def _sub_datelike(self, other):
raise TypeError("cannot subtract a datelike from a {cls}"
.format(cls=type(self).__name__))

def _add_delta(self, delta):
"""
Add a timedelta-like, Tick, or TimedeltaIndex-like object
to self.

Parameters
----------
delta : timedelta, np.timedelta64, Tick, TimedeltaArray, TimedeltaIndex

Returns
-------
result : same type as self

Notes
-----
The result's name is set outside of _add_delta by the calling
method (__add__ or __sub__)
"""
if isinstance(delta, (Tick, timedelta, np.timedelta64)):
new_values = self._add_delta_td(delta)
elif is_timedelta64_dtype(delta):
# ndarray[timedelta64] --> wrap in TimedeltaArray/Index
new_values = self._add_delta_tdi(delta)

return type(self)(new_values, freq='infer')

def _add_datelike(self, other):
# adding a timedeltaindex to a datetimelike
from pandas.core.arrays import DatetimeArrayMixin
Expand Down
0