def _add_timedeltalike_scalar(self, other): """ Parameters ---------- other : timedelta, Tick, np.timedelta64 Returns ------- PeriodArray """ if not isinstance(self.freq, Tick): # We cannot add timedelta-like to non-tick PeriodArray raise raise_on_incompatible(self, other) if notna(other): # Convert to an integer increment of our own freq, disallowing # e.g. 30seconds if our freq is minutes. try: inc = delta_to_nanoseconds(other, reso=self.freq._reso, round_ok=False) except ValueError as err: # "Cannot losslessly convert units" raise raise_on_incompatible(self, other) from err return self._addsub_int_array_or_scalar(inc, operator.add) return super()._add_timedeltalike_scalar(other)
def _check_timedeltalike_freq_compat(self, other): """ Arithmetic operations with timedelta-like scalars or array `other` are only valid if `other` is an integer multiple of `self.freq`. If the operation is valid, find that integer multiple. Otherwise, raise because the operation is invalid. Parameters ---------- other : timedelta, np.timedelta64, Tick, ndarray[timedelta64], TimedeltaArray, TimedeltaIndex Returns ------- multiple : int or ndarray[int64] Raises ------ IncompatibleFrequency """ assert isinstance(self.freq, Tick) # checked by calling function base_nanos = self.freq.base.nanos if isinstance(other, (timedelta, np.timedelta64, Tick)): nanos = delta_to_nanoseconds(other) elif isinstance(other, np.ndarray): # numpy timedelta64 array; all entries must be compatible assert other.dtype.kind == "m" if other.dtype != TD64NS_DTYPE: # i.e. non-nano unit # TODO: disallow unit-less timedelta64 other = other.astype(TD64NS_DTYPE) nanos = other.view("i8") else: # TimedeltaArray/Index nanos = other.asi8 if np.all(nanos % base_nanos == 0): # nanos being added is an integer multiple of the # base-frequency to self.freq delta = nanos // base_nanos # delta is the integer (or integer-array) number of periods # by which will be added to self. return delta raise raise_on_incompatible(self, other)
def _check_timedeltalike_freq_compat(self, other): """ Arithmetic operations with timedelta-like scalars or array `other` are only valid if `other` is an integer multiple of `self.freq`. If the operation is valid, find that integer multiple. Otherwise, raise because the operation is invalid. Parameters ---------- other : timedelta, np.timedelta64, Tick, ndarray[timedelta64], TimedeltaArray, TimedeltaIndex Returns ------- multiple : int or ndarray[int64] Raises ------ IncompatibleFrequency """ assert isinstance(self.freq, Tick) # checked by calling function base_nanos = self.freq.base.nanos if isinstance(other, (timedelta, np.timedelta64, Tick)): nanos = delta_to_nanoseconds(other) elif isinstance(other, np.ndarray): # numpy timedelta64 array; all entries must be compatible assert other.dtype.kind == "m" other = astype_overflowsafe(other, TD64NS_DTYPE, copy=False) # error: Incompatible types in assignment (expression has type # "ndarray[Any, dtype[Any]]", variable has type "int") nanos = other.view("i8") # type: ignore[assignment] else: # TimedeltaArray/Index nanos = other.asi8 if np.all(nanos % base_nanos == 0): # nanos being added is an integer multiple of the # base-frequency to self.freq delta = nanos // base_nanos # delta is the integer (or integer-array) number of periods # by which will be added to self. return delta raise raise_on_incompatible(self, other)