Skip to content

Commit b814929

Browse files
jbrockmendelPingviinituutti
authored andcommitted
Implement+Test Tick.__rtruediv__ (pandas-dev#24832)
1 parent c4637c8 commit b814929

File tree

3 files changed

+59
-0
lines changed

3 files changed

+59
-0
lines changed

pandas/_libs/tslibs/offsets.pyx

+16
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ from numpy cimport int64_t
1818
cnp.import_array()
1919

2020

21+
from pandas._libs.tslibs cimport util
2122
from pandas._libs.tslibs.util cimport is_string_object, is_integer_object
2223

2324
from pandas._libs.tslibs.ccalendar import MONTHS, DAYS
@@ -408,6 +409,10 @@ class _BaseOffset(object):
408409
return self.apply(other)
409410

410411
def __mul__(self, other):
412+
if hasattr(other, "_typ"):
413+
return NotImplemented
414+
if util.is_array(other):
415+
return np.array([self * x for x in other])
411416
return type(self)(n=other * self.n, normalize=self.normalize,
412417
**self.kwds)
413418

@@ -458,6 +463,9 @@ class _BaseOffset(object):
458463
TypeError if `int(n)` raises
459464
ValueError if n != int(n)
460465
"""
466+
if util.is_timedelta64_object(n):
467+
raise TypeError('`n` argument must be an integer, '
468+
'got {ntype}'.format(ntype=type(n)))
461469
try:
462470
nint = int(n)
463471
except (ValueError, TypeError):
@@ -533,12 +541,20 @@ class _Tick(object):
533541
can do isinstance checks on _Tick and avoid importing tseries.offsets
534542
"""
535543

544+
# ensure that reversed-ops with numpy scalars return NotImplemented
545+
__array_priority__ = 1000
546+
536547
def __truediv__(self, other):
537548
result = self.delta.__truediv__(other)
538549
return _wrap_timedelta_result(result)
539550

551+
def __rtruediv__(self, other):
552+
result = self.delta.__rtruediv__(other)
553+
return _wrap_timedelta_result(result)
554+
540555
if PY2:
541556
__div__ = __truediv__
557+
__rdiv__ = __rtruediv__
542558

543559

544560
# ----------------------------------------------------------------------

pandas/tests/tseries/offsets/test_offsets.py

+20
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,26 @@ def test_offset_n(self, offset_types):
257257
mul_offset = offset * 3
258258
assert mul_offset.n == 3
259259

260+
def test_offset_timedelta64_arg(self, offset_types):
261+
# check that offset._validate_n raises TypeError on a timedelt64
262+
# object
263+
off = self._get_offset(offset_types)
264+
265+
td64 = np.timedelta64(4567, 's')
266+
with pytest.raises(TypeError, match="argument must be an integer"):
267+
type(off)(n=td64, **off.kwds)
268+
269+
def test_offset_mul_ndarray(self, offset_types):
270+
off = self._get_offset(offset_types)
271+
272+
expected = np.array([[off, off * 2], [off * 3, off * 4]])
273+
274+
result = np.array([[1, 2], [3, 4]]) * off
275+
tm.assert_numpy_array_equal(result, expected)
276+
277+
result = off * np.array([[1, 2], [3, 4]])
278+
tm.assert_numpy_array_equal(result, expected)
279+
260280
def test_offset_freqstr(self, offset_types):
261281
offset = self._get_offset(offset_types)
262282

pandas/tests/tseries/offsets/test_ticks.py

+23
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import pytest
1212

1313
from pandas import Timedelta, Timestamp
14+
import pandas.util.testing as tm
1415

1516
from pandas.tseries import offsets
1617
from pandas.tseries.offsets import Hour, Micro, Milli, Minute, Nano, Second
@@ -262,6 +263,28 @@ def test_tick_division(cls):
262263
assert result.delta == off.delta / .001
263264

264265

266+
@pytest.mark.parametrize('cls', tick_classes)
267+
def test_tick_rdiv(cls):
268+
off = cls(10)
269+
delta = off.delta
270+
td64 = delta.to_timedelta64()
271+
272+
with pytest.raises(TypeError):
273+
2 / off
274+
with pytest.raises(TypeError):
275+
2.0 / off
276+
277+
assert (td64 * 2.5) / off == 2.5
278+
279+
if cls is not Nano:
280+
# skip pytimedelta for Nano since it gets dropped
281+
assert (delta.to_pytimedelta() * 2) / off == 2
282+
283+
result = np.array([2 * td64, td64]) / off
284+
expected = np.array([2., 1.])
285+
tm.assert_numpy_array_equal(result, expected)
286+
287+
265288
@pytest.mark.parametrize('cls1', tick_classes)
266289
@pytest.mark.parametrize('cls2', tick_classes)
267290
def test_tick_zero(cls1, cls2):

0 commit comments

Comments
 (0)