123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691 |
- # -*- coding: utf-8 -*-
- """
- Tests for scalar Timedelta arithmetic ops
- """
- from datetime import datetime, timedelta
- import operator
- import numpy as np
- import pytest
- import pandas as pd
- from pandas import NaT, Timedelta, Timestamp
- from pandas.core import ops
- import pandas.util.testing as tm
- class TestTimedeltaAdditionSubtraction(object):
- """
- Tests for Timedelta methods:
- __add__, __radd__,
- __sub__, __rsub__
- """
- @pytest.mark.parametrize('ten_seconds', [
- Timedelta(10, unit='s'),
- timedelta(seconds=10),
- np.timedelta64(10, 's'),
- np.timedelta64(10000000000, 'ns'),
- pd.offsets.Second(10)])
- def test_td_add_sub_ten_seconds(self, ten_seconds):
- # GH#6808
- base = Timestamp('20130101 09:01:12.123456')
- expected_add = Timestamp('20130101 09:01:22.123456')
- expected_sub = Timestamp('20130101 09:01:02.123456')
- result = base + ten_seconds
- assert result == expected_add
- result = base - ten_seconds
- assert result == expected_sub
- @pytest.mark.parametrize('one_day_ten_secs', [
- Timedelta('1 day, 00:00:10'),
- Timedelta('1 days, 00:00:10'),
- timedelta(days=1, seconds=10),
- np.timedelta64(1, 'D') + np.timedelta64(10, 's'),
- pd.offsets.Day() + pd.offsets.Second(10)])
- def test_td_add_sub_one_day_ten_seconds(self, one_day_ten_secs):
- # GH#6808
- base = Timestamp('20130102 09:01:12.123456')
- expected_add = Timestamp('20130103 09:01:22.123456')
- expected_sub = Timestamp('20130101 09:01:02.123456')
- result = base + one_day_ten_secs
- assert result == expected_add
- result = base - one_day_ten_secs
- assert result == expected_sub
- @pytest.mark.parametrize('op', [operator.add, ops.radd])
- def test_td_add_datetimelike_scalar(self, op):
- # GH#19738
- td = Timedelta(10, unit='d')
- result = op(td, datetime(2016, 1, 1))
- if op is operator.add:
- # datetime + Timedelta does _not_ call Timedelta.__radd__,
- # so we get a datetime back instead of a Timestamp
- assert isinstance(result, Timestamp)
- assert result == Timestamp(2016, 1, 11)
- result = op(td, Timestamp('2018-01-12 18:09'))
- assert isinstance(result, Timestamp)
- assert result == Timestamp('2018-01-22 18:09')
- result = op(td, np.datetime64('2018-01-12'))
- assert isinstance(result, Timestamp)
- assert result == Timestamp('2018-01-22')
- result = op(td, NaT)
- assert result is NaT
- @pytest.mark.parametrize('op', [operator.add, ops.radd])
- def test_td_add_td(self, op):
- td = Timedelta(10, unit='d')
- result = op(td, Timedelta(days=10))
- assert isinstance(result, Timedelta)
- assert result == Timedelta(days=20)
- @pytest.mark.parametrize('op', [operator.add, ops.radd])
- def test_td_add_pytimedelta(self, op):
- td = Timedelta(10, unit='d')
- result = op(td, timedelta(days=9))
- assert isinstance(result, Timedelta)
- assert result == Timedelta(days=19)
- @pytest.mark.parametrize('op', [operator.add, ops.radd])
- def test_td_add_timedelta64(self, op):
- td = Timedelta(10, unit='d')
- result = op(td, np.timedelta64(-4, 'D'))
- assert isinstance(result, Timedelta)
- assert result == Timedelta(days=6)
- @pytest.mark.parametrize('op', [operator.add, ops.radd])
- def test_td_add_offset(self, op):
- td = Timedelta(10, unit='d')
- result = op(td, pd.offsets.Hour(6))
- assert isinstance(result, Timedelta)
- assert result == Timedelta(days=10, hours=6)
- def test_td_sub_td(self):
- td = Timedelta(10, unit='d')
- expected = Timedelta(0, unit='ns')
- result = td - td
- assert isinstance(result, Timedelta)
- assert result == expected
- def test_td_sub_pytimedelta(self):
- td = Timedelta(10, unit='d')
- expected = Timedelta(0, unit='ns')
- result = td - td.to_pytimedelta()
- assert isinstance(result, Timedelta)
- assert result == expected
- result = td.to_pytimedelta() - td
- assert isinstance(result, Timedelta)
- assert result == expected
- def test_td_sub_timedelta64(self):
- td = Timedelta(10, unit='d')
- expected = Timedelta(0, unit='ns')
- result = td - td.to_timedelta64()
- assert isinstance(result, Timedelta)
- assert result == expected
- result = td.to_timedelta64() - td
- assert isinstance(result, Timedelta)
- assert result == expected
- def test_td_sub_nat(self):
- # In this context pd.NaT is treated as timedelta-like
- td = Timedelta(10, unit='d')
- result = td - NaT
- assert result is NaT
- def test_td_sub_td64_nat(self):
- td = Timedelta(10, unit='d')
- td_nat = np.timedelta64('NaT')
- result = td - td_nat
- assert result is NaT
- result = td_nat - td
- assert result is NaT
- def test_td_sub_offset(self):
- td = Timedelta(10, unit='d')
- result = td - pd.offsets.Hour(1)
- assert isinstance(result, Timedelta)
- assert result == Timedelta(239, unit='h')
- def test_td_add_sub_numeric_raises(self):
- td = Timedelta(10, unit='d')
- for other in [2, 2.0, np.int64(2), np.float64(2)]:
- with pytest.raises(TypeError):
- td + other
- with pytest.raises(TypeError):
- other + td
- with pytest.raises(TypeError):
- td - other
- with pytest.raises(TypeError):
- other - td
- def test_td_rsub_nat(self):
- td = Timedelta(10, unit='d')
- result = NaT - td
- assert result is NaT
- result = np.datetime64('NaT') - td
- assert result is NaT
- def test_td_rsub_offset(self):
- result = pd.offsets.Hour(1) - Timedelta(10, unit='d')
- assert isinstance(result, Timedelta)
- assert result == Timedelta(-239, unit='h')
- def test_td_sub_timedeltalike_object_dtype_array(self):
- # GH#21980
- arr = np.array([Timestamp('20130101 9:01'),
- Timestamp('20121230 9:02')])
- exp = np.array([Timestamp('20121231 9:01'),
- Timestamp('20121229 9:02')])
- res = arr - Timedelta('1D')
- tm.assert_numpy_array_equal(res, exp)
- def test_td_sub_mixed_most_timedeltalike_object_dtype_array(self):
- # GH#21980
- now = Timestamp.now()
- arr = np.array([now,
- Timedelta('1D'),
- np.timedelta64(2, 'h')])
- exp = np.array([now - Timedelta('1D'),
- Timedelta('0D'),
- np.timedelta64(2, 'h') - Timedelta('1D')])
- res = arr - Timedelta('1D')
- tm.assert_numpy_array_equal(res, exp)
- def test_td_rsub_mixed_most_timedeltalike_object_dtype_array(self):
- # GH#21980
- now = Timestamp.now()
- arr = np.array([now,
- Timedelta('1D'),
- np.timedelta64(2, 'h')])
- with pytest.raises(TypeError):
- Timedelta('1D') - arr
- @pytest.mark.parametrize('op', [operator.add, ops.radd])
- def test_td_add_timedeltalike_object_dtype_array(self, op):
- # GH#21980
- arr = np.array([Timestamp('20130101 9:01'),
- Timestamp('20121230 9:02')])
- exp = np.array([Timestamp('20130102 9:01'),
- Timestamp('20121231 9:02')])
- res = op(arr, Timedelta('1D'))
- tm.assert_numpy_array_equal(res, exp)
- @pytest.mark.parametrize('op', [operator.add, ops.radd])
- def test_td_add_mixed_timedeltalike_object_dtype_array(self, op):
- # GH#21980
- now = Timestamp.now()
- arr = np.array([now,
- Timedelta('1D')])
- exp = np.array([now + Timedelta('1D'),
- Timedelta('2D')])
- res = op(arr, Timedelta('1D'))
- tm.assert_numpy_array_equal(res, exp)
- class TestTimedeltaMultiplicationDivision(object):
- """
- Tests for Timedelta methods:
- __mul__, __rmul__,
- __div__, __rdiv__,
- __truediv__, __rtruediv__,
- __floordiv__, __rfloordiv__,
- __mod__, __rmod__,
- __divmod__, __rdivmod__
- """
- # ---------------------------------------------------------------
- # Timedelta.__mul__, __rmul__
- @pytest.mark.parametrize('td_nat', [NaT,
- np.timedelta64('NaT', 'ns'),
- np.timedelta64('NaT')])
- @pytest.mark.parametrize('op', [operator.mul, ops.rmul])
- def test_td_mul_nat(self, op, td_nat):
- # GH#19819
- td = Timedelta(10, unit='d')
- with pytest.raises(TypeError):
- op(td, td_nat)
- @pytest.mark.parametrize('nan', [np.nan, np.float64('NaN'), float('nan')])
- @pytest.mark.parametrize('op', [operator.mul, ops.rmul])
- def test_td_mul_nan(self, op, nan):
- # np.float64('NaN') has a 'dtype' attr, avoid treating as array
- td = Timedelta(10, unit='d')
- result = op(td, nan)
- assert result is NaT
- @pytest.mark.parametrize('op', [operator.mul, ops.rmul])
- def test_td_mul_scalar(self, op):
- # GH#19738
- td = Timedelta(minutes=3)
- result = op(td, 2)
- assert result == Timedelta(minutes=6)
- result = op(td, 1.5)
- assert result == Timedelta(minutes=4, seconds=30)
- assert op(td, np.nan) is NaT
- assert op(-1, td).value == -1 * td.value
- assert op(-1.0, td).value == -1.0 * td.value
- with pytest.raises(TypeError):
- # timedelta * datetime is gibberish
- op(td, Timestamp(2016, 1, 2))
- with pytest.raises(TypeError):
- # invalid multiply with another timedelta
- op(td, td)
- # ---------------------------------------------------------------
- # Timedelta.__div__, __truediv__
- def test_td_div_timedeltalike_scalar(self):
- # GH#19738
- td = Timedelta(10, unit='d')
- result = td / pd.offsets.Hour(1)
- assert result == 240
- assert td / td == 1
- assert td / np.timedelta64(60, 'h') == 4
- assert np.isnan(td / NaT)
- def test_td_div_numeric_scalar(self):
- # GH#19738
- td = Timedelta(10, unit='d')
- result = td / 2
- assert isinstance(result, Timedelta)
- assert result == Timedelta(days=5)
- result = td / 5.0
- assert isinstance(result, Timedelta)
- assert result == Timedelta(days=2)
- @pytest.mark.parametrize('nan', [np.nan, np.float64('NaN'), float('nan')])
- def test_td_div_nan(self, nan):
- # np.float64('NaN') has a 'dtype' attr, avoid treating as array
- td = Timedelta(10, unit='d')
- result = td / nan
- assert result is NaT
- result = td // nan
- assert result is NaT
- # ---------------------------------------------------------------
- # Timedelta.__rdiv__
- def test_td_rdiv_timedeltalike_scalar(self):
- # GH#19738
- td = Timedelta(10, unit='d')
- result = pd.offsets.Hour(1) / td
- assert result == 1 / 240.0
- assert np.timedelta64(60, 'h') / td == 0.25
- # ---------------------------------------------------------------
- # Timedelta.__floordiv__
- def test_td_floordiv_timedeltalike_scalar(self):
- # GH#18846
- td = Timedelta(hours=3, minutes=4)
- scalar = Timedelta(hours=3, minutes=3)
- assert td // scalar == 1
- assert -td // scalar.to_pytimedelta() == -2
- assert (2 * td) // scalar.to_timedelta64() == 2
- def test_td_floordiv_null_scalar(self):
- # GH#18846
- td = Timedelta(hours=3, minutes=4)
- assert td // np.nan is NaT
- assert np.isnan(td // NaT)
- assert np.isnan(td // np.timedelta64('NaT'))
- def test_td_floordiv_offsets(self):
- # GH#19738
- td = Timedelta(hours=3, minutes=4)
- assert td // pd.offsets.Hour(1) == 3
- assert td // pd.offsets.Minute(2) == 92
- def test_td_floordiv_invalid_scalar(self):
- # GH#18846
- td = Timedelta(hours=3, minutes=4)
- with pytest.raises(TypeError):
- td // np.datetime64('2016-01-01', dtype='datetime64[us]')
- def test_td_floordiv_numeric_scalar(self):
- # GH#18846
- td = Timedelta(hours=3, minutes=4)
- expected = Timedelta(hours=1, minutes=32)
- assert td // 2 == expected
- assert td // 2.0 == expected
- assert td // np.float64(2.0) == expected
- assert td // np.int32(2.0) == expected
- assert td // np.uint8(2.0) == expected
- def test_td_floordiv_timedeltalike_array(self):
- # GH#18846
- td = Timedelta(hours=3, minutes=4)
- scalar = Timedelta(hours=3, minutes=3)
- # Array-like others
- assert td // np.array(scalar.to_timedelta64()) == 1
- res = (3 * td) // np.array([scalar.to_timedelta64()])
- expected = np.array([3], dtype=np.int64)
- tm.assert_numpy_array_equal(res, expected)
- res = (10 * td) // np.array([scalar.to_timedelta64(),
- np.timedelta64('NaT')])
- expected = np.array([10, np.nan])
- tm.assert_numpy_array_equal(res, expected)
- def test_td_floordiv_numeric_series(self):
- # GH#18846
- td = Timedelta(hours=3, minutes=4)
- ser = pd.Series([1], dtype=np.int64)
- res = td // ser
- assert res.dtype.kind == 'm'
- # ---------------------------------------------------------------
- # Timedelta.__rfloordiv__
- def test_td_rfloordiv_timedeltalike_scalar(self):
- # GH#18846
- td = Timedelta(hours=3, minutes=3)
- scalar = Timedelta(hours=3, minutes=4)
- # scalar others
- # x // Timedelta is defined only for timedelta-like x. int-like,
- # float-like, and date-like, in particular, should all either
- # a) raise TypeError directly or
- # b) return NotImplemented, following which the reversed
- # operation will raise TypeError.
- assert td.__rfloordiv__(scalar) == 1
- assert (-td).__rfloordiv__(scalar.to_pytimedelta()) == -2
- assert (2 * td).__rfloordiv__(scalar.to_timedelta64()) == 0
- def test_td_rfloordiv_null_scalar(self):
- # GH#18846
- td = Timedelta(hours=3, minutes=3)
- assert np.isnan(td.__rfloordiv__(NaT))
- assert np.isnan(td.__rfloordiv__(np.timedelta64('NaT')))
- def test_td_rfloordiv_offsets(self):
- # GH#19738
- assert pd.offsets.Hour(1) // Timedelta(minutes=25) == 2
- def test_td_rfloordiv_invalid_scalar(self):
- # GH#18846
- td = Timedelta(hours=3, minutes=3)
- dt64 = np.datetime64('2016-01-01', dtype='datetime64[us]')
- with pytest.raises(TypeError):
- td.__rfloordiv__(dt64)
- def test_td_rfloordiv_numeric_scalar(self):
- # GH#18846
- td = Timedelta(hours=3, minutes=3)
- assert td.__rfloordiv__(np.nan) is NotImplemented
- assert td.__rfloordiv__(3.5) is NotImplemented
- assert td.__rfloordiv__(2) is NotImplemented
- with pytest.raises(TypeError):
- td.__rfloordiv__(np.float64(2.0))
- with pytest.raises(TypeError):
- td.__rfloordiv__(np.uint8(9))
- with tm.assert_produces_warning(FutureWarning):
- # GH-19761: Change to TypeError.
- td.__rfloordiv__(np.int32(2.0))
- def test_td_rfloordiv_timedeltalike_array(self):
- # GH#18846
- td = Timedelta(hours=3, minutes=3)
- scalar = Timedelta(hours=3, minutes=4)
- # Array-like others
- assert td.__rfloordiv__(np.array(scalar.to_timedelta64())) == 1
- res = td.__rfloordiv__(np.array([(3 * scalar).to_timedelta64()]))
- expected = np.array([3], dtype=np.int64)
- tm.assert_numpy_array_equal(res, expected)
- arr = np.array([(10 * scalar).to_timedelta64(),
- np.timedelta64('NaT')])
- res = td.__rfloordiv__(arr)
- expected = np.array([10, np.nan])
- tm.assert_numpy_array_equal(res, expected)
- def test_td_rfloordiv_numeric_series(self):
- # GH#18846
- td = Timedelta(hours=3, minutes=3)
- ser = pd.Series([1], dtype=np.int64)
- res = td.__rfloordiv__(ser)
- assert res is NotImplemented
- with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
- # TODO: GH-19761. Change to TypeError.
- ser // td
- # ----------------------------------------------------------------
- # Timedelta.__mod__, __rmod__
- def test_mod_timedeltalike(self):
- # GH#19365
- td = Timedelta(hours=37)
- # Timedelta-like others
- result = td % Timedelta(hours=6)
- assert isinstance(result, Timedelta)
- assert result == Timedelta(hours=1)
- result = td % timedelta(minutes=60)
- assert isinstance(result, Timedelta)
- assert result == Timedelta(0)
- result = td % NaT
- assert result is NaT
- def test_mod_timedelta64_nat(self):
- # GH#19365
- td = Timedelta(hours=37)
- result = td % np.timedelta64('NaT', 'ns')
- assert result is NaT
- def test_mod_timedelta64(self):
- # GH#19365
- td = Timedelta(hours=37)
- result = td % np.timedelta64(2, 'h')
- assert isinstance(result, Timedelta)
- assert result == Timedelta(hours=1)
- def test_mod_offset(self):
- # GH#19365
- td = Timedelta(hours=37)
- result = td % pd.offsets.Hour(5)
- assert isinstance(result, Timedelta)
- assert result == Timedelta(hours=2)
- def test_mod_numeric(self):
- # GH#19365
- td = Timedelta(hours=37)
- # Numeric Others
- result = td % 2
- assert isinstance(result, Timedelta)
- assert result == Timedelta(0)
- result = td % 1e12
- assert isinstance(result, Timedelta)
- assert result == Timedelta(minutes=3, seconds=20)
- result = td % int(1e12)
- assert isinstance(result, Timedelta)
- assert result == Timedelta(minutes=3, seconds=20)
- def test_mod_invalid(self):
- # GH#19365
- td = Timedelta(hours=37)
- with pytest.raises(TypeError):
- td % Timestamp('2018-01-22')
- with pytest.raises(TypeError):
- td % []
- def test_rmod_pytimedelta(self):
- # GH#19365
- td = Timedelta(minutes=3)
- result = timedelta(minutes=4) % td
- assert isinstance(result, Timedelta)
- assert result == Timedelta(minutes=1)
- def test_rmod_timedelta64(self):
- # GH#19365
- td = Timedelta(minutes=3)
- result = np.timedelta64(5, 'm') % td
- assert isinstance(result, Timedelta)
- assert result == Timedelta(minutes=2)
- def test_rmod_invalid(self):
- # GH#19365
- td = Timedelta(minutes=3)
- with pytest.raises(TypeError):
- Timestamp('2018-01-22') % td
- with pytest.raises(TypeError):
- 15 % td
- with pytest.raises(TypeError):
- 16.0 % td
- with pytest.raises(TypeError):
- np.array([22, 24]) % td
- # ----------------------------------------------------------------
- # Timedelta.__divmod__, __rdivmod__
- def test_divmod_numeric(self):
- # GH#19365
- td = Timedelta(days=2, hours=6)
- result = divmod(td, 53 * 3600 * 1e9)
- assert result[0] == Timedelta(1, unit='ns')
- assert isinstance(result[1], Timedelta)
- assert result[1] == Timedelta(hours=1)
- assert result
- result = divmod(td, np.nan)
- assert result[0] is NaT
- assert result[1] is NaT
- def test_divmod(self):
- # GH#19365
- td = Timedelta(days=2, hours=6)
- result = divmod(td, timedelta(days=1))
- assert result[0] == 2
- assert isinstance(result[1], Timedelta)
- assert result[1] == Timedelta(hours=6)
- result = divmod(td, 54)
- assert result[0] == Timedelta(hours=1)
- assert isinstance(result[1], Timedelta)
- assert result[1] == Timedelta(0)
- result = divmod(td, NaT)
- assert np.isnan(result[0])
- assert result[1] is NaT
- def test_divmod_offset(self):
- # GH#19365
- td = Timedelta(days=2, hours=6)
- result = divmod(td, pd.offsets.Hour(-4))
- assert result[0] == -14
- assert isinstance(result[1], Timedelta)
- assert result[1] == Timedelta(hours=-2)
- def test_divmod_invalid(self):
- # GH#19365
- td = Timedelta(days=2, hours=6)
- with pytest.raises(TypeError):
- divmod(td, Timestamp('2018-01-22'))
- def test_rdivmod_pytimedelta(self):
- # GH#19365
- result = divmod(timedelta(days=2, hours=6), Timedelta(days=1))
- assert result[0] == 2
- assert isinstance(result[1], Timedelta)
- assert result[1] == Timedelta(hours=6)
- def test_rdivmod_offset(self):
- result = divmod(pd.offsets.Hour(54), Timedelta(hours=-4))
- assert result[0] == -14
- assert isinstance(result[1], Timedelta)
- assert result[1] == Timedelta(hours=-2)
- def test_rdivmod_invalid(self):
- # GH#19365
- td = Timedelta(minutes=3)
- with pytest.raises(TypeError):
- divmod(Timestamp('2018-01-22'), td)
- with pytest.raises(TypeError):
- divmod(15, td)
- with pytest.raises(TypeError):
- divmod(16.0, td)
- with pytest.raises(TypeError):
- divmod(np.array([22, 24]), td)
- # ----------------------------------------------------------------
- @pytest.mark.parametrize('op', [
- operator.mul,
- ops.rmul,
- operator.truediv,
- ops.rdiv,
- ops.rsub])
- @pytest.mark.parametrize('arr', [
- np.array([Timestamp('20130101 9:01'), Timestamp('20121230 9:02')]),
- np.array([Timestamp.now(), Timedelta('1D')])
- ])
- def test_td_op_timedelta_timedeltalike_array(self, op, arr):
- with pytest.raises(TypeError):
- op(arr, Timedelta('1D'))
|