def _maybe_convert_timedelta(self, other): if isinstance( other, (timedelta, np.timedelta64, offsets.Tick, np.ndarray)): offset = frequencies.to_offset(self.freq.rule_code) if isinstance(offset, offsets.Tick): if isinstance(other, np.ndarray): nanos = np.vectorize(delta_to_nanoseconds)(other) else: nanos = delta_to_nanoseconds(other) offset_nanos = delta_to_nanoseconds(offset) check = np.all(nanos % offset_nanos == 0) if check: return nanos // offset_nanos elif isinstance(other, offsets.DateOffset): freqstr = other.rule_code base = frequencies.get_base_alias(freqstr) if base == self.freq.rule_code: return other.n msg = _DIFFERENT_FREQ_INDEX.format(self.freqstr, other.freqstr) raise IncompatibleFrequency(msg) elif is_integer(other): # integer is passed to .shift via # _add_datetimelike_methods basically # but ufunc may pass integer to _add_delta return other # raise when input doesn't have freq msg = "Input has different freq from PeriodIndex(freq={0})" raise IncompatibleFrequency(msg.format(self.freqstr))
def _maybe_convert_timedelta(self, other): if isinstance(other, (timedelta, np.timedelta64, Tick, np.ndarray)): offset = frequencies.to_offset(self.freq.rule_code) if isinstance(offset, Tick): if isinstance(other, np.ndarray): nanos = np.vectorize(delta_to_nanoseconds)(other) else: nanos = delta_to_nanoseconds(other) offset_nanos = delta_to_nanoseconds(offset) check = np.all(nanos % offset_nanos == 0) if check: return nanos // offset_nanos elif isinstance(other, DateOffset): freqstr = other.rule_code base = frequencies.get_base_alias(freqstr) if base == self.freq.rule_code: return other.n msg = _DIFFERENT_FREQ_INDEX.format(self.freqstr, other.freqstr) raise IncompatibleFrequency(msg) elif is_integer(other): # integer is passed to .shift via # _add_datetimelike_methods basically # but ufunc may pass integer to _add_delta return other # raise when input doesn't have freq msg = "Input has different freq from PeriodIndex(freq={0})" raise IncompatibleFrequency(msg.format(self.freqstr))
def test_delta_to_nanoseconds_td64_MY_raises(): td = np.timedelta64(1234, "Y") with pytest.raises(ValueError, match="0, 10"): delta_to_nanoseconds(td) td = np.timedelta64(1234, "M") with pytest.raises(ValueError, match="1, 10"): delta_to_nanoseconds(td)
def test_delta_to_nanoseconds(): obj = np.timedelta64(14, 'D') result = delta_to_nanoseconds(obj) assert result == 14 * 24 * 3600 * 1e9 obj = pd.Timedelta(minutes=-7) result = delta_to_nanoseconds(obj) assert result == -7 * 60 * 1e9 obj = pd.Timedelta(minutes=-7).to_pytimedelta() result = delta_to_nanoseconds(obj) assert result == -7 * 60 * 1e9 obj = pd.offsets.Nano(125) result = delta_to_nanoseconds(obj) assert result == 125 obj = 1 result = delta_to_nanoseconds(obj) assert obj == 1 obj = np.int64(2) result = delta_to_nanoseconds(obj) assert obj == 2 obj = np.int32(3) result = delta_to_nanoseconds(obj) assert result == 3 obj = np.array([123456789], dtype='m8[ns]') with pytest.raises(TypeError): delta_to_nanoseconds(obj)
def test_delta_to_nanoseconds_td64_MY_raises(): msg = ("delta_to_nanoseconds does not support Y or M units, " "as their duration in nanoseconds is ambiguous") td = np.timedelta64(1234, "Y") with pytest.raises(ValueError, match=msg): delta_to_nanoseconds(td) td = np.timedelta64(1234, "M") with pytest.raises(ValueError, match=msg): delta_to_nanoseconds(td)
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 own_offset = frequencies.to_offset(self.freq.rule_code) base_nanos = delta_to_nanoseconds(own_offset) 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 != _TD_DTYPE: # i.e. non-nano unit # TODO: disallow unit-less timedelta64 other = other.astype(_TD_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 IncompatibleFrequency("Input has different freq from " "{cls}(freq={freqstr})" .format(cls=type(self).__name__, freqstr=self.freqstr))
def test_delta_to_nanoseconds_error(): obj = np.array([123456789], dtype="m8[ns]") with pytest.raises(TypeError, match="<class 'numpy.ndarray'>"): delta_to_nanoseconds(obj) with pytest.raises(TypeError, match="float"): delta_to_nanoseconds(1.5) with pytest.raises(TypeError, match="int"): delta_to_nanoseconds(1) with pytest.raises(TypeError, match="int"): delta_to_nanoseconds(np.int64(2)) with pytest.raises(TypeError, match="int"): delta_to_nanoseconds(np.int32(3))
def _add_delta_td(self, other): assert isinstance(other, (timedelta, np.timedelta64, Tick)) nanos = delta_to_nanoseconds(other) own_offset = frequencies.to_offset(self.freq.rule_code) if isinstance(own_offset, Tick): offset_nanos = delta_to_nanoseconds(own_offset) if np.all(nanos % offset_nanos == 0): return self.shift(nanos // offset_nanos) # raise when input doesn't have freq raise IncompatibleFrequency("Input has different freq from " "{cls}(freq={freqstr})".format( cls=type(self).__name__, freqstr=self.freqstr))
def _add_delta_td(self, other): assert isinstance(other, (timedelta, np.timedelta64, Tick)) nanos = delta_to_nanoseconds(other) own_offset = frequencies.to_offset(self.freq.rule_code) if isinstance(own_offset, Tick): offset_nanos = delta_to_nanoseconds(own_offset) if np.all(nanos % offset_nanos == 0): return self.shift(nanos // offset_nanos) # raise when input doesn't have freq raise IncompatibleFrequency("Input has different freq from " "{cls}(freq={freqstr})" .format(cls=type(self).__name__, freqstr=self.freqstr))
def _maybe_convert_timedelta(self, other): """ Convert timedelta-like input to an integer multiple of self.freq Parameters ---------- other : timedelta, np.timedelta64, DateOffset, int, np.ndarray Returns ------- converted : int, np.ndarray[int64] Raises ------ IncompatibleFrequency : if the input cannot be written as a multiple of self.freq. Note IncompatibleFrequency subclasses ValueError. """ if isinstance( other, (timedelta, np.timedelta64, Tick, np.ndarray)): offset = frequencies.to_offset(self.freq.rule_code) if isinstance(offset, Tick): if isinstance(other, np.ndarray): nanos = np.vectorize(delta_to_nanoseconds)(other) else: nanos = delta_to_nanoseconds(other) offset_nanos = delta_to_nanoseconds(offset) check = np.all(nanos % offset_nanos == 0) if check: return nanos // offset_nanos elif isinstance(other, DateOffset): freqstr = other.rule_code base = frequencies.get_base_alias(freqstr) if base == self.freq.rule_code: return other.n msg = DIFFERENT_FREQ_INDEX.format(self.freqstr, other.freqstr) raise IncompatibleFrequency(msg) elif lib.is_integer(other): # integer is passed to .shift via # _add_datetimelike_methods basically # but ufunc may pass integer to _add_delta return other # raise when input doesn't have freq msg = "Input has different freq from {cls}(freq={freqstr})" raise IncompatibleFrequency(msg.format(cls=type(self).__name__, freqstr=self.freqstr))
def _maybe_convert_timedelta(self, other): """ Convert timedelta-like input to an integer multiple of self.freq Parameters ---------- other : timedelta, np.timedelta64, DateOffset, int, np.ndarray Returns ------- converted : int, np.ndarray[int64] Raises ------ IncompatibleFrequency : if the input cannot be written as a multiple of self.freq. Note IncompatibleFrequency subclasses ValueError. """ if isinstance( other, (timedelta, np.timedelta64, Tick, np.ndarray)): offset = frequencies.to_offset(self.freq.rule_code) if isinstance(offset, Tick): if isinstance(other, np.ndarray): nanos = np.vectorize(delta_to_nanoseconds)(other) else: nanos = delta_to_nanoseconds(other) offset_nanos = delta_to_nanoseconds(offset) check = np.all(nanos % offset_nanos == 0) if check: return nanos // offset_nanos elif isinstance(other, DateOffset): freqstr = other.rule_code base = frequencies.get_base_alias(freqstr) if base == self.freq.rule_code: return other.n msg = DIFFERENT_FREQ_INDEX.format(self.freqstr, other.freqstr) raise IncompatibleFrequency(msg) elif lib.is_integer(other): # integer is passed to .shift via # _add_datetimelike_methods basically # but ufunc may pass integer to _add_delta return other # raise when input doesn't have freq msg = "Input has different freq from {cls}(freq={freqstr})" raise IncompatibleFrequency(msg.format(cls=type(self).__name__, freqstr=self.freqstr))
def _add_delta_td(self, other): # add a delta of a timedeltalike # return the i8 result view 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 return new_values.view('i8')
def _add_delta_td(self, other): # add a delta of a timedeltalike # return the i8 result view 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 return new_values.view('i8')
def _add_timedeltalike_scalar(self, other): """ Add a delta of a timedeltalike return the i8 result view """ inc = delta_to_nanoseconds(other) new_values = checked_add_with_arr(self.asi8, inc, arr_mask=self._isnan).view('i8') new_values = self._maybe_mask_results(new_values) return new_values.view('i8')
def _add_timedeltalike_scalar(self, other): """ Add a delta of a timedeltalike return the i8 result view """ if isna(other): # i.e np.timedelta64("NaT"), not recognized by delta_to_nanoseconds new_values = np.empty(len(self), dtype='i8') new_values[:] = iNaT return new_values inc = delta_to_nanoseconds(other) new_values = checked_add_with_arr(self.asi8, inc, arr_mask=self._isnan).view('i8') new_values = self._maybe_mask_results(new_values) return new_values.view('i8')
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 test_delta_to_nanoseconds_error(): obj = np.array([123456789], dtype="m8[ns]") with pytest.raises(TypeError, match="<class 'numpy.ndarray'>"): delta_to_nanoseconds(obj)
def test_delta_to_nanoseconds(obj, expected): result = delta_to_nanoseconds(obj) assert result == expected
def test_huge_nanoseconds_overflow(): # GH 32402 assert delta_to_nanoseconds(Timedelta(1e10)) == 1e10 assert delta_to_nanoseconds(Timedelta(nanoseconds=1e10)) == 1e10
def test_delta_to_nanoseconds(obj, expected): result = delta_to_nanoseconds(obj) assert result == expected
def test_delta_to_nanoseconds_error(): obj = np.array([123456789], dtype="m8[ns]") with pytest.raises(TypeError, match="<(class|type) 'numpy.ndarray'>"): delta_to_nanoseconds(obj)