laywerrobot/lib/python3.6/site-packages/pandas/tests/scalar/timedelta/test_arithmetic.py
2020-08-27 21:55:39 +02:00

618 lines
19 KiB
Python

# -*- 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
import pandas.util.testing as tm
from pandas.core import ops
from pandas import Timedelta, Timestamp, NaT
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
with pytest.raises(TypeError):
op(td, 2)
with pytest.raises(TypeError):
op(td, 2.0)
@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
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
def test_td_sub_nat(self):
td = Timedelta(10, unit='d')
result = td - NaT
assert result is NaT
def test_td_sub_td64_nat(self):
td = Timedelta(10, unit='d')
result = td - np.timedelta64('NaT')
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_sub_numeric_raises(self):
td = td = Timedelta(10, unit='d')
with pytest.raises(TypeError):
td - 2
with pytest.raises(TypeError):
td - 2.0
def test_td_rsub_pytimedelta(self):
td = Timedelta(10, unit='d')
expected = Timedelta(0, unit='ns')
result = td.to_pytimedelta() - td
assert isinstance(result, Timedelta)
assert result == expected
def test_td_rsub_timedelta64(self):
td = Timedelta(10, unit='d')
expected = Timedelta(0, unit='ns')
result = td.to_timedelta64() - td
assert isinstance(result, Timedelta)
assert result == expected
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_td64_nat(self):
td = Timedelta(10, unit='d')
result = np.timedelta64('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_rsub_numeric_raises(self):
td = td = Timedelta(10, unit='d')
with pytest.raises(TypeError):
2 - td
with pytest.raises(TypeError):
2.0 - td
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', [pd.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('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)
# ---------------------------------------------------------------
# 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
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)
# ----------------------------------------------------------------
# Timedelta.__mod__, __rmod__
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 % pd.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):
pd.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 pd.NaT
assert result[1] is pd.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, pd.NaT)
assert np.isnan(result[0])
assert result[1] is pd.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, pd.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(pd.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)