You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			2470 lines
		
	
	
		
			88 KiB
		
	
	
	
		
			Python
		
	
			
		
		
	
	
			2470 lines
		
	
	
		
			88 KiB
		
	
	
	
		
			Python
		
	
# Arithmetic tests for DataFrame/Series/Index/Array classes that should
 | 
						|
# behave identically.
 | 
						|
# Specifically for datetime64 and datetime64tz dtypes
 | 
						|
from datetime import (
 | 
						|
    datetime,
 | 
						|
    time,
 | 
						|
    timedelta,
 | 
						|
)
 | 
						|
from itertools import (
 | 
						|
    product,
 | 
						|
    starmap,
 | 
						|
)
 | 
						|
import operator
 | 
						|
 | 
						|
import numpy as np
 | 
						|
import pytest
 | 
						|
import pytz
 | 
						|
 | 
						|
from pandas._libs.tslibs.conversion import localize_pydatetime
 | 
						|
from pandas._libs.tslibs.offsets import shift_months
 | 
						|
from pandas.errors import PerformanceWarning
 | 
						|
 | 
						|
import pandas as pd
 | 
						|
from pandas import (
 | 
						|
    DateOffset,
 | 
						|
    DatetimeIndex,
 | 
						|
    NaT,
 | 
						|
    Period,
 | 
						|
    Series,
 | 
						|
    Timedelta,
 | 
						|
    TimedeltaIndex,
 | 
						|
    Timestamp,
 | 
						|
    date_range,
 | 
						|
)
 | 
						|
import pandas._testing as tm
 | 
						|
from pandas.core import roperator
 | 
						|
from pandas.tests.arithmetic.common import (
 | 
						|
    assert_cannot_add,
 | 
						|
    assert_invalid_addsub_type,
 | 
						|
    assert_invalid_comparison,
 | 
						|
    get_upcast_box,
 | 
						|
)
 | 
						|
 | 
						|
# ------------------------------------------------------------------
 | 
						|
# Comparisons
 | 
						|
 | 
						|
 | 
						|
class TestDatetime64ArrayLikeComparisons:
 | 
						|
    # Comparison tests for datetime64 vectors fully parametrized over
 | 
						|
    #  DataFrame/Series/DatetimeIndex/DatetimeArray.  Ideally all comparison
 | 
						|
    #  tests will eventually end up here.
 | 
						|
 | 
						|
    def test_compare_zerodim(self, tz_naive_fixture, box_with_array):
 | 
						|
        # Test comparison with zero-dimensional array is unboxed
 | 
						|
        tz = tz_naive_fixture
 | 
						|
        box = box_with_array
 | 
						|
        dti = date_range("20130101", periods=3, tz=tz)
 | 
						|
 | 
						|
        other = np.array(dti.to_numpy()[0])
 | 
						|
 | 
						|
        dtarr = tm.box_expected(dti, box)
 | 
						|
        xbox = get_upcast_box(dtarr, other, True)
 | 
						|
        result = dtarr <= other
 | 
						|
        expected = np.array([True, False, False])
 | 
						|
        expected = tm.box_expected(expected, xbox)
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
 | 
						|
    @pytest.mark.parametrize(
 | 
						|
        "other",
 | 
						|
        [
 | 
						|
            "foo",
 | 
						|
            -1,
 | 
						|
            99,
 | 
						|
            4.0,
 | 
						|
            object(),
 | 
						|
            timedelta(days=2),
 | 
						|
            # GH#19800, GH#19301 datetime.date comparison raises to
 | 
						|
            #  match DatetimeIndex/Timestamp.  This also matches the behavior
 | 
						|
            #  of stdlib datetime.datetime
 | 
						|
            datetime(2001, 1, 1).date(),
 | 
						|
            # GH#19301 None and NaN are *not* cast to NaT for comparisons
 | 
						|
            None,
 | 
						|
            np.nan,
 | 
						|
        ],
 | 
						|
    )
 | 
						|
    def test_dt64arr_cmp_scalar_invalid(self, other, tz_naive_fixture, box_with_array):
 | 
						|
        # GH#22074, GH#15966
 | 
						|
        tz = tz_naive_fixture
 | 
						|
 | 
						|
        rng = date_range("1/1/2000", periods=10, tz=tz)
 | 
						|
        dtarr = tm.box_expected(rng, box_with_array)
 | 
						|
        assert_invalid_comparison(dtarr, other, box_with_array)
 | 
						|
 | 
						|
    @pytest.mark.parametrize(
 | 
						|
        "other",
 | 
						|
        [
 | 
						|
            # GH#4968 invalid date/int comparisons
 | 
						|
            list(range(10)),
 | 
						|
            np.arange(10),
 | 
						|
            np.arange(10).astype(np.float32),
 | 
						|
            np.arange(10).astype(object),
 | 
						|
            pd.timedelta_range("1ns", periods=10).array,
 | 
						|
            np.array(pd.timedelta_range("1ns", periods=10)),
 | 
						|
            list(pd.timedelta_range("1ns", periods=10)),
 | 
						|
            pd.timedelta_range("1 Day", periods=10).astype(object),
 | 
						|
            pd.period_range("1971-01-01", freq="D", periods=10).array,
 | 
						|
            pd.period_range("1971-01-01", freq="D", periods=10).astype(object),
 | 
						|
        ],
 | 
						|
    )
 | 
						|
    def test_dt64arr_cmp_arraylike_invalid(
 | 
						|
        self, other, tz_naive_fixture, box_with_array
 | 
						|
    ):
 | 
						|
        tz = tz_naive_fixture
 | 
						|
 | 
						|
        dta = date_range("1970-01-01", freq="ns", periods=10, tz=tz)._data
 | 
						|
        obj = tm.box_expected(dta, box_with_array)
 | 
						|
        assert_invalid_comparison(obj, other, box_with_array)
 | 
						|
 | 
						|
    def test_dt64arr_cmp_mixed_invalid(self, tz_naive_fixture):
 | 
						|
        tz = tz_naive_fixture
 | 
						|
 | 
						|
        dta = date_range("1970-01-01", freq="h", periods=5, tz=tz)._data
 | 
						|
 | 
						|
        other = np.array([0, 1, 2, dta[3], Timedelta(days=1)])
 | 
						|
        result = dta == other
 | 
						|
        expected = np.array([False, False, False, True, False])
 | 
						|
        tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
        result = dta != other
 | 
						|
        tm.assert_numpy_array_equal(result, ~expected)
 | 
						|
 | 
						|
        msg = "Invalid comparison between|Cannot compare type|not supported between"
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            dta < other
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            dta > other
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            dta <= other
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            dta >= other
 | 
						|
 | 
						|
    def test_dt64arr_nat_comparison(self, tz_naive_fixture, box_with_array):
 | 
						|
        # GH#22242, GH#22163 DataFrame considered NaT == ts incorrectly
 | 
						|
        tz = tz_naive_fixture
 | 
						|
        box = box_with_array
 | 
						|
 | 
						|
        ts = Timestamp("2021-01-01", tz=tz)
 | 
						|
        ser = Series([ts, NaT])
 | 
						|
 | 
						|
        obj = tm.box_expected(ser, box)
 | 
						|
        xbox = get_upcast_box(obj, ts, True)
 | 
						|
 | 
						|
        expected = Series([True, False], dtype=np.bool_)
 | 
						|
        expected = tm.box_expected(expected, xbox)
 | 
						|
 | 
						|
        result = obj == ts
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
 | 
						|
 | 
						|
class TestDatetime64SeriesComparison:
 | 
						|
    # TODO: moved from tests.series.test_operators; needs cleanup
 | 
						|
 | 
						|
    @pytest.mark.parametrize(
 | 
						|
        "pair",
 | 
						|
        [
 | 
						|
            (
 | 
						|
                [Timestamp("2011-01-01"), NaT, Timestamp("2011-01-03")],
 | 
						|
                [NaT, NaT, Timestamp("2011-01-03")],
 | 
						|
            ),
 | 
						|
            (
 | 
						|
                [Timedelta("1 days"), NaT, Timedelta("3 days")],
 | 
						|
                [NaT, NaT, Timedelta("3 days")],
 | 
						|
            ),
 | 
						|
            (
 | 
						|
                [Period("2011-01", freq="M"), NaT, Period("2011-03", freq="M")],
 | 
						|
                [NaT, NaT, Period("2011-03", freq="M")],
 | 
						|
            ),
 | 
						|
        ],
 | 
						|
    )
 | 
						|
    @pytest.mark.parametrize("reverse", [True, False])
 | 
						|
    @pytest.mark.parametrize("dtype", [None, object])
 | 
						|
    @pytest.mark.parametrize(
 | 
						|
        "op, expected",
 | 
						|
        [
 | 
						|
            (operator.eq, Series([False, False, True])),
 | 
						|
            (operator.ne, Series([True, True, False])),
 | 
						|
            (operator.lt, Series([False, False, False])),
 | 
						|
            (operator.gt, Series([False, False, False])),
 | 
						|
            (operator.ge, Series([False, False, True])),
 | 
						|
            (operator.le, Series([False, False, True])),
 | 
						|
        ],
 | 
						|
    )
 | 
						|
    def test_nat_comparisons(
 | 
						|
        self,
 | 
						|
        dtype,
 | 
						|
        index_or_series,
 | 
						|
        reverse,
 | 
						|
        pair,
 | 
						|
        op,
 | 
						|
        expected,
 | 
						|
    ):
 | 
						|
        box = index_or_series
 | 
						|
        lhs, rhs = pair
 | 
						|
        if reverse:
 | 
						|
            # add lhs / rhs switched data
 | 
						|
            lhs, rhs = rhs, lhs
 | 
						|
 | 
						|
        left = Series(lhs, dtype=dtype)
 | 
						|
        right = box(rhs, dtype=dtype)
 | 
						|
 | 
						|
        result = op(left, right)
 | 
						|
 | 
						|
        tm.assert_series_equal(result, expected)
 | 
						|
 | 
						|
    @pytest.mark.parametrize(
 | 
						|
        "data",
 | 
						|
        [
 | 
						|
            [Timestamp("2011-01-01"), NaT, Timestamp("2011-01-03")],
 | 
						|
            [Timedelta("1 days"), NaT, Timedelta("3 days")],
 | 
						|
            [Period("2011-01", freq="M"), NaT, Period("2011-03", freq="M")],
 | 
						|
        ],
 | 
						|
    )
 | 
						|
    @pytest.mark.parametrize("dtype", [None, object])
 | 
						|
    def test_nat_comparisons_scalar(self, dtype, data, box_with_array):
 | 
						|
        box = box_with_array
 | 
						|
 | 
						|
        left = Series(data, dtype=dtype)
 | 
						|
        left = tm.box_expected(left, box)
 | 
						|
        xbox = get_upcast_box(left, NaT, True)
 | 
						|
 | 
						|
        expected = [False, False, False]
 | 
						|
        expected = tm.box_expected(expected, xbox)
 | 
						|
        if box is pd.array and dtype is object:
 | 
						|
            expected = pd.array(expected, dtype="bool")
 | 
						|
 | 
						|
        tm.assert_equal(left == NaT, expected)
 | 
						|
        tm.assert_equal(NaT == left, expected)
 | 
						|
 | 
						|
        expected = [True, True, True]
 | 
						|
        expected = tm.box_expected(expected, xbox)
 | 
						|
        if box is pd.array and dtype is object:
 | 
						|
            expected = pd.array(expected, dtype="bool")
 | 
						|
        tm.assert_equal(left != NaT, expected)
 | 
						|
        tm.assert_equal(NaT != left, expected)
 | 
						|
 | 
						|
        expected = [False, False, False]
 | 
						|
        expected = tm.box_expected(expected, xbox)
 | 
						|
        if box is pd.array and dtype is object:
 | 
						|
            expected = pd.array(expected, dtype="bool")
 | 
						|
        tm.assert_equal(left < NaT, expected)
 | 
						|
        tm.assert_equal(NaT > left, expected)
 | 
						|
        tm.assert_equal(left <= NaT, expected)
 | 
						|
        tm.assert_equal(NaT >= left, expected)
 | 
						|
 | 
						|
        tm.assert_equal(left > NaT, expected)
 | 
						|
        tm.assert_equal(NaT < left, expected)
 | 
						|
        tm.assert_equal(left >= NaT, expected)
 | 
						|
        tm.assert_equal(NaT <= left, expected)
 | 
						|
 | 
						|
    @pytest.mark.parametrize("val", [datetime(2000, 1, 4), datetime(2000, 1, 5)])
 | 
						|
    def test_series_comparison_scalars(self, val):
 | 
						|
        series = Series(date_range("1/1/2000", periods=10))
 | 
						|
 | 
						|
        result = series > val
 | 
						|
        expected = Series([x > val for x in series])
 | 
						|
        tm.assert_series_equal(result, expected)
 | 
						|
 | 
						|
    @pytest.mark.parametrize(
 | 
						|
        "left,right", [("lt", "gt"), ("le", "ge"), ("eq", "eq"), ("ne", "ne")]
 | 
						|
    )
 | 
						|
    def test_timestamp_compare_series(self, left, right):
 | 
						|
        # see gh-4982
 | 
						|
        # Make sure we can compare Timestamps on the right AND left hand side.
 | 
						|
        ser = Series(date_range("20010101", periods=10), name="dates")
 | 
						|
        s_nat = ser.copy(deep=True)
 | 
						|
 | 
						|
        ser[0] = Timestamp("nat")
 | 
						|
        ser[3] = Timestamp("nat")
 | 
						|
 | 
						|
        left_f = getattr(operator, left)
 | 
						|
        right_f = getattr(operator, right)
 | 
						|
 | 
						|
        # No NaT
 | 
						|
        expected = left_f(ser, Timestamp("20010109"))
 | 
						|
        result = right_f(Timestamp("20010109"), ser)
 | 
						|
        tm.assert_series_equal(result, expected)
 | 
						|
 | 
						|
        # NaT
 | 
						|
        expected = left_f(ser, Timestamp("nat"))
 | 
						|
        result = right_f(Timestamp("nat"), ser)
 | 
						|
        tm.assert_series_equal(result, expected)
 | 
						|
 | 
						|
        # Compare to Timestamp with series containing NaT
 | 
						|
        expected = left_f(s_nat, Timestamp("20010109"))
 | 
						|
        result = right_f(Timestamp("20010109"), s_nat)
 | 
						|
        tm.assert_series_equal(result, expected)
 | 
						|
 | 
						|
        # Compare to NaT with series containing NaT
 | 
						|
        expected = left_f(s_nat, NaT)
 | 
						|
        result = right_f(NaT, s_nat)
 | 
						|
        tm.assert_series_equal(result, expected)
 | 
						|
 | 
						|
    def test_dt64arr_timestamp_equality(self, box_with_array):
 | 
						|
        # GH#11034
 | 
						|
        box = box_with_array
 | 
						|
 | 
						|
        ser = Series([Timestamp("2000-01-29 01:59:00"), Timestamp("2000-01-30"), NaT])
 | 
						|
        ser = tm.box_expected(ser, box)
 | 
						|
        xbox = get_upcast_box(ser, ser, True)
 | 
						|
 | 
						|
        result = ser != ser
 | 
						|
        expected = tm.box_expected([False, False, True], xbox)
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
 | 
						|
        if box is pd.DataFrame:
 | 
						|
            # alignment for frame vs series comparisons deprecated
 | 
						|
            #  in GH#46795 enforced 2.0
 | 
						|
            with pytest.raises(ValueError, match="not aligned"):
 | 
						|
                ser != ser[0]
 | 
						|
 | 
						|
        else:
 | 
						|
            result = ser != ser[0]
 | 
						|
            expected = tm.box_expected([False, True, True], xbox)
 | 
						|
            tm.assert_equal(result, expected)
 | 
						|
 | 
						|
        if box is pd.DataFrame:
 | 
						|
            # alignment for frame vs series comparisons deprecated
 | 
						|
            #  in GH#46795 enforced 2.0
 | 
						|
            with pytest.raises(ValueError, match="not aligned"):
 | 
						|
                ser != ser[2]
 | 
						|
        else:
 | 
						|
            result = ser != ser[2]
 | 
						|
            expected = tm.box_expected([True, True, True], xbox)
 | 
						|
            tm.assert_equal(result, expected)
 | 
						|
 | 
						|
        result = ser == ser
 | 
						|
        expected = tm.box_expected([True, True, False], xbox)
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
 | 
						|
        if box is pd.DataFrame:
 | 
						|
            # alignment for frame vs series comparisons deprecated
 | 
						|
            #  in GH#46795 enforced 2.0
 | 
						|
            with pytest.raises(ValueError, match="not aligned"):
 | 
						|
                ser == ser[0]
 | 
						|
        else:
 | 
						|
            result = ser == ser[0]
 | 
						|
            expected = tm.box_expected([True, False, False], xbox)
 | 
						|
            tm.assert_equal(result, expected)
 | 
						|
 | 
						|
        if box is pd.DataFrame:
 | 
						|
            # alignment for frame vs series comparisons deprecated
 | 
						|
            #  in GH#46795 enforced 2.0
 | 
						|
            with pytest.raises(ValueError, match="not aligned"):
 | 
						|
                ser == ser[2]
 | 
						|
        else:
 | 
						|
            result = ser == ser[2]
 | 
						|
            expected = tm.box_expected([False, False, False], xbox)
 | 
						|
            tm.assert_equal(result, expected)
 | 
						|
 | 
						|
    @pytest.mark.parametrize(
 | 
						|
        "datetimelike",
 | 
						|
        [
 | 
						|
            Timestamp("20130101"),
 | 
						|
            datetime(2013, 1, 1),
 | 
						|
            np.datetime64("2013-01-01T00:00", "ns"),
 | 
						|
        ],
 | 
						|
    )
 | 
						|
    @pytest.mark.parametrize(
 | 
						|
        "op,expected",
 | 
						|
        [
 | 
						|
            (operator.lt, [True, False, False, False]),
 | 
						|
            (operator.le, [True, True, False, False]),
 | 
						|
            (operator.eq, [False, True, False, False]),
 | 
						|
            (operator.gt, [False, False, False, True]),
 | 
						|
        ],
 | 
						|
    )
 | 
						|
    def test_dt64_compare_datetime_scalar(self, datetimelike, op, expected):
 | 
						|
        # GH#17965, test for ability to compare datetime64[ns] columns
 | 
						|
        #  to datetimelike
 | 
						|
        ser = Series(
 | 
						|
            [
 | 
						|
                Timestamp("20120101"),
 | 
						|
                Timestamp("20130101"),
 | 
						|
                np.nan,
 | 
						|
                Timestamp("20130103"),
 | 
						|
            ],
 | 
						|
            name="A",
 | 
						|
        )
 | 
						|
        result = op(ser, datetimelike)
 | 
						|
        expected = Series(expected, name="A")
 | 
						|
        tm.assert_series_equal(result, expected)
 | 
						|
 | 
						|
 | 
						|
class TestDatetimeIndexComparisons:
 | 
						|
    # TODO: moved from tests.indexes.test_base; parametrize and de-duplicate
 | 
						|
    def test_comparators(self, comparison_op):
 | 
						|
        index = date_range("2020-01-01", periods=10)
 | 
						|
        element = index[len(index) // 2]
 | 
						|
        element = Timestamp(element).to_datetime64()
 | 
						|
 | 
						|
        arr = np.array(index)
 | 
						|
        arr_result = comparison_op(arr, element)
 | 
						|
        index_result = comparison_op(index, element)
 | 
						|
 | 
						|
        assert isinstance(index_result, np.ndarray)
 | 
						|
        tm.assert_numpy_array_equal(arr_result, index_result)
 | 
						|
 | 
						|
    @pytest.mark.parametrize(
 | 
						|
        "other",
 | 
						|
        [datetime(2016, 1, 1), Timestamp("2016-01-01"), np.datetime64("2016-01-01")],
 | 
						|
    )
 | 
						|
    def test_dti_cmp_datetimelike(self, other, tz_naive_fixture):
 | 
						|
        tz = tz_naive_fixture
 | 
						|
        dti = date_range("2016-01-01", periods=2, tz=tz)
 | 
						|
        if tz is not None:
 | 
						|
            if isinstance(other, np.datetime64):
 | 
						|
                pytest.skip(f"{type(other).__name__} is not tz aware")
 | 
						|
            other = localize_pydatetime(other, dti.tzinfo)
 | 
						|
 | 
						|
        result = dti == other
 | 
						|
        expected = np.array([True, False])
 | 
						|
        tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
        result = dti > other
 | 
						|
        expected = np.array([False, True])
 | 
						|
        tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
        result = dti >= other
 | 
						|
        expected = np.array([True, True])
 | 
						|
        tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
        result = dti < other
 | 
						|
        expected = np.array([False, False])
 | 
						|
        tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
        result = dti <= other
 | 
						|
        expected = np.array([True, False])
 | 
						|
        tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
    @pytest.mark.parametrize("dtype", [None, object])
 | 
						|
    def test_dti_cmp_nat(self, dtype, box_with_array):
 | 
						|
        left = DatetimeIndex([Timestamp("2011-01-01"), NaT, Timestamp("2011-01-03")])
 | 
						|
        right = DatetimeIndex([NaT, NaT, Timestamp("2011-01-03")])
 | 
						|
 | 
						|
        left = tm.box_expected(left, box_with_array)
 | 
						|
        right = tm.box_expected(right, box_with_array)
 | 
						|
        xbox = get_upcast_box(left, right, True)
 | 
						|
 | 
						|
        lhs, rhs = left, right
 | 
						|
        if dtype is object:
 | 
						|
            lhs, rhs = left.astype(object), right.astype(object)
 | 
						|
 | 
						|
        result = rhs == lhs
 | 
						|
        expected = np.array([False, False, True])
 | 
						|
        expected = tm.box_expected(expected, xbox)
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
 | 
						|
        result = lhs != rhs
 | 
						|
        expected = np.array([True, True, False])
 | 
						|
        expected = tm.box_expected(expected, xbox)
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
 | 
						|
        expected = np.array([False, False, False])
 | 
						|
        expected = tm.box_expected(expected, xbox)
 | 
						|
        tm.assert_equal(lhs == NaT, expected)
 | 
						|
        tm.assert_equal(NaT == rhs, expected)
 | 
						|
 | 
						|
        expected = np.array([True, True, True])
 | 
						|
        expected = tm.box_expected(expected, xbox)
 | 
						|
        tm.assert_equal(lhs != NaT, expected)
 | 
						|
        tm.assert_equal(NaT != lhs, expected)
 | 
						|
 | 
						|
        expected = np.array([False, False, False])
 | 
						|
        expected = tm.box_expected(expected, xbox)
 | 
						|
        tm.assert_equal(lhs < NaT, expected)
 | 
						|
        tm.assert_equal(NaT > lhs, expected)
 | 
						|
 | 
						|
    def test_dti_cmp_nat_behaves_like_float_cmp_nan(self):
 | 
						|
        fidx1 = pd.Index([1.0, np.nan, 3.0, np.nan, 5.0, 7.0])
 | 
						|
        fidx2 = pd.Index([2.0, 3.0, np.nan, np.nan, 6.0, 7.0])
 | 
						|
 | 
						|
        didx1 = DatetimeIndex(
 | 
						|
            ["2014-01-01", NaT, "2014-03-01", NaT, "2014-05-01", "2014-07-01"]
 | 
						|
        )
 | 
						|
        didx2 = DatetimeIndex(
 | 
						|
            ["2014-02-01", "2014-03-01", NaT, NaT, "2014-06-01", "2014-07-01"]
 | 
						|
        )
 | 
						|
        darr = np.array(
 | 
						|
            [
 | 
						|
                np.datetime64("2014-02-01 00:00"),
 | 
						|
                np.datetime64("2014-03-01 00:00"),
 | 
						|
                np.datetime64("nat"),
 | 
						|
                np.datetime64("nat"),
 | 
						|
                np.datetime64("2014-06-01 00:00"),
 | 
						|
                np.datetime64("2014-07-01 00:00"),
 | 
						|
            ]
 | 
						|
        )
 | 
						|
 | 
						|
        cases = [(fidx1, fidx2), (didx1, didx2), (didx1, darr)]
 | 
						|
 | 
						|
        # Check pd.NaT is handles as the same as np.nan
 | 
						|
        with tm.assert_produces_warning(None):
 | 
						|
            for idx1, idx2 in cases:
 | 
						|
                result = idx1 < idx2
 | 
						|
                expected = np.array([True, False, False, False, True, False])
 | 
						|
                tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
                result = idx2 > idx1
 | 
						|
                expected = np.array([True, False, False, False, True, False])
 | 
						|
                tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
                result = idx1 <= idx2
 | 
						|
                expected = np.array([True, False, False, False, True, True])
 | 
						|
                tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
                result = idx2 >= idx1
 | 
						|
                expected = np.array([True, False, False, False, True, True])
 | 
						|
                tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
                result = idx1 == idx2
 | 
						|
                expected = np.array([False, False, False, False, False, True])
 | 
						|
                tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
                result = idx1 != idx2
 | 
						|
                expected = np.array([True, True, True, True, True, False])
 | 
						|
                tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
        with tm.assert_produces_warning(None):
 | 
						|
            for idx1, val in [(fidx1, np.nan), (didx1, NaT)]:
 | 
						|
                result = idx1 < val
 | 
						|
                expected = np.array([False, False, False, False, False, False])
 | 
						|
                tm.assert_numpy_array_equal(result, expected)
 | 
						|
                result = idx1 > val
 | 
						|
                tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
                result = idx1 <= val
 | 
						|
                tm.assert_numpy_array_equal(result, expected)
 | 
						|
                result = idx1 >= val
 | 
						|
                tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
                result = idx1 == val
 | 
						|
                tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
                result = idx1 != val
 | 
						|
                expected = np.array([True, True, True, True, True, True])
 | 
						|
                tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
        # Check pd.NaT is handles as the same as np.nan
 | 
						|
        with tm.assert_produces_warning(None):
 | 
						|
            for idx1, val in [(fidx1, 3), (didx1, datetime(2014, 3, 1))]:
 | 
						|
                result = idx1 < val
 | 
						|
                expected = np.array([True, False, False, False, False, False])
 | 
						|
                tm.assert_numpy_array_equal(result, expected)
 | 
						|
                result = idx1 > val
 | 
						|
                expected = np.array([False, False, False, False, True, True])
 | 
						|
                tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
                result = idx1 <= val
 | 
						|
                expected = np.array([True, False, True, False, False, False])
 | 
						|
                tm.assert_numpy_array_equal(result, expected)
 | 
						|
                result = idx1 >= val
 | 
						|
                expected = np.array([False, False, True, False, True, True])
 | 
						|
                tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
                result = idx1 == val
 | 
						|
                expected = np.array([False, False, True, False, False, False])
 | 
						|
                tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
                result = idx1 != val
 | 
						|
                expected = np.array([True, True, False, True, True, True])
 | 
						|
                tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
    def test_comparison_tzawareness_compat(self, comparison_op, box_with_array):
 | 
						|
        # GH#18162
 | 
						|
        op = comparison_op
 | 
						|
        box = box_with_array
 | 
						|
 | 
						|
        dr = date_range("2016-01-01", periods=6)
 | 
						|
        dz = dr.tz_localize("US/Pacific")
 | 
						|
 | 
						|
        dr = tm.box_expected(dr, box)
 | 
						|
        dz = tm.box_expected(dz, box)
 | 
						|
 | 
						|
        if box is pd.DataFrame:
 | 
						|
            tolist = lambda x: x.astype(object).values.tolist()[0]
 | 
						|
        else:
 | 
						|
            tolist = list
 | 
						|
 | 
						|
        if op not in [operator.eq, operator.ne]:
 | 
						|
            msg = (
 | 
						|
                r"Invalid comparison between dtype=datetime64\[ns.*\] "
 | 
						|
                "and (Timestamp|DatetimeArray|list|ndarray)"
 | 
						|
            )
 | 
						|
            with pytest.raises(TypeError, match=msg):
 | 
						|
                op(dr, dz)
 | 
						|
 | 
						|
            with pytest.raises(TypeError, match=msg):
 | 
						|
                op(dr, tolist(dz))
 | 
						|
            with pytest.raises(TypeError, match=msg):
 | 
						|
                op(dr, np.array(tolist(dz), dtype=object))
 | 
						|
            with pytest.raises(TypeError, match=msg):
 | 
						|
                op(dz, dr)
 | 
						|
 | 
						|
            with pytest.raises(TypeError, match=msg):
 | 
						|
                op(dz, tolist(dr))
 | 
						|
            with pytest.raises(TypeError, match=msg):
 | 
						|
                op(dz, np.array(tolist(dr), dtype=object))
 | 
						|
 | 
						|
        # The aware==aware and naive==naive comparisons should *not* raise
 | 
						|
        assert np.all(dr == dr)
 | 
						|
        assert np.all(dr == tolist(dr))
 | 
						|
        assert np.all(tolist(dr) == dr)
 | 
						|
        assert np.all(np.array(tolist(dr), dtype=object) == dr)
 | 
						|
        assert np.all(dr == np.array(tolist(dr), dtype=object))
 | 
						|
 | 
						|
        assert np.all(dz == dz)
 | 
						|
        assert np.all(dz == tolist(dz))
 | 
						|
        assert np.all(tolist(dz) == dz)
 | 
						|
        assert np.all(np.array(tolist(dz), dtype=object) == dz)
 | 
						|
        assert np.all(dz == np.array(tolist(dz), dtype=object))
 | 
						|
 | 
						|
    def test_comparison_tzawareness_compat_scalars(self, comparison_op, box_with_array):
 | 
						|
        # GH#18162
 | 
						|
        op = comparison_op
 | 
						|
 | 
						|
        dr = date_range("2016-01-01", periods=6)
 | 
						|
        dz = dr.tz_localize("US/Pacific")
 | 
						|
 | 
						|
        dr = tm.box_expected(dr, box_with_array)
 | 
						|
        dz = tm.box_expected(dz, box_with_array)
 | 
						|
 | 
						|
        # Check comparisons against scalar Timestamps
 | 
						|
        ts = Timestamp("2000-03-14 01:59")
 | 
						|
        ts_tz = Timestamp("2000-03-14 01:59", tz="Europe/Amsterdam")
 | 
						|
 | 
						|
        assert np.all(dr > ts)
 | 
						|
        msg = r"Invalid comparison between dtype=datetime64\[ns.*\] and Timestamp"
 | 
						|
        if op not in [operator.eq, operator.ne]:
 | 
						|
            with pytest.raises(TypeError, match=msg):
 | 
						|
                op(dr, ts_tz)
 | 
						|
 | 
						|
        assert np.all(dz > ts_tz)
 | 
						|
        if op not in [operator.eq, operator.ne]:
 | 
						|
            with pytest.raises(TypeError, match=msg):
 | 
						|
                op(dz, ts)
 | 
						|
 | 
						|
        if op not in [operator.eq, operator.ne]:
 | 
						|
            # GH#12601: Check comparison against Timestamps and DatetimeIndex
 | 
						|
            with pytest.raises(TypeError, match=msg):
 | 
						|
                op(ts, dz)
 | 
						|
 | 
						|
    @pytest.mark.parametrize(
 | 
						|
        "other",
 | 
						|
        [datetime(2016, 1, 1), Timestamp("2016-01-01"), np.datetime64("2016-01-01")],
 | 
						|
    )
 | 
						|
    # Bug in NumPy? https://github.com/numpy/numpy/issues/13841
 | 
						|
    # Raising in __eq__ will fallback to NumPy, which warns, fails,
 | 
						|
    # then re-raises the original exception. So we just need to ignore.
 | 
						|
    @pytest.mark.filterwarnings("ignore:elementwise comp:DeprecationWarning")
 | 
						|
    def test_scalar_comparison_tzawareness(
 | 
						|
        self, comparison_op, other, tz_aware_fixture, box_with_array
 | 
						|
    ):
 | 
						|
        op = comparison_op
 | 
						|
        tz = tz_aware_fixture
 | 
						|
        dti = date_range("2016-01-01", periods=2, tz=tz)
 | 
						|
 | 
						|
        dtarr = tm.box_expected(dti, box_with_array)
 | 
						|
        xbox = get_upcast_box(dtarr, other, True)
 | 
						|
        if op in [operator.eq, operator.ne]:
 | 
						|
            exbool = op is operator.ne
 | 
						|
            expected = np.array([exbool, exbool], dtype=bool)
 | 
						|
            expected = tm.box_expected(expected, xbox)
 | 
						|
 | 
						|
            result = op(dtarr, other)
 | 
						|
            tm.assert_equal(result, expected)
 | 
						|
 | 
						|
            result = op(other, dtarr)
 | 
						|
            tm.assert_equal(result, expected)
 | 
						|
        else:
 | 
						|
            msg = (
 | 
						|
                r"Invalid comparison between dtype=datetime64\[ns, .*\] "
 | 
						|
                f"and {type(other).__name__}"
 | 
						|
            )
 | 
						|
            with pytest.raises(TypeError, match=msg):
 | 
						|
                op(dtarr, other)
 | 
						|
            with pytest.raises(TypeError, match=msg):
 | 
						|
                op(other, dtarr)
 | 
						|
 | 
						|
    def test_nat_comparison_tzawareness(self, comparison_op):
 | 
						|
        # GH#19276
 | 
						|
        # tzaware DatetimeIndex should not raise when compared to NaT
 | 
						|
        op = comparison_op
 | 
						|
 | 
						|
        dti = DatetimeIndex(
 | 
						|
            ["2014-01-01", NaT, "2014-03-01", NaT, "2014-05-01", "2014-07-01"]
 | 
						|
        )
 | 
						|
        expected = np.array([op == operator.ne] * len(dti))
 | 
						|
        result = op(dti, NaT)
 | 
						|
        tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
        result = op(dti.tz_localize("US/Pacific"), NaT)
 | 
						|
        tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
    def test_dti_cmp_str(self, tz_naive_fixture):
 | 
						|
        # GH#22074
 | 
						|
        # regardless of tz, we expect these comparisons are valid
 | 
						|
        tz = tz_naive_fixture
 | 
						|
        rng = date_range("1/1/2000", periods=10, tz=tz)
 | 
						|
        other = "1/1/2000"
 | 
						|
 | 
						|
        result = rng == other
 | 
						|
        expected = np.array([True] + [False] * 9)
 | 
						|
        tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
        result = rng != other
 | 
						|
        expected = np.array([False] + [True] * 9)
 | 
						|
        tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
        result = rng < other
 | 
						|
        expected = np.array([False] * 10)
 | 
						|
        tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
        result = rng <= other
 | 
						|
        expected = np.array([True] + [False] * 9)
 | 
						|
        tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
        result = rng > other
 | 
						|
        expected = np.array([False] + [True] * 9)
 | 
						|
        tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
        result = rng >= other
 | 
						|
        expected = np.array([True] * 10)
 | 
						|
        tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
    def test_dti_cmp_list(self):
 | 
						|
        rng = date_range("1/1/2000", periods=10)
 | 
						|
 | 
						|
        result = rng == list(rng)
 | 
						|
        expected = rng == rng
 | 
						|
        tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
    @pytest.mark.parametrize(
 | 
						|
        "other",
 | 
						|
        [
 | 
						|
            pd.timedelta_range("1D", periods=10),
 | 
						|
            pd.timedelta_range("1D", periods=10).to_series(),
 | 
						|
            pd.timedelta_range("1D", periods=10).asi8.view("m8[ns]"),
 | 
						|
        ],
 | 
						|
        ids=lambda x: type(x).__name__,
 | 
						|
    )
 | 
						|
    def test_dti_cmp_tdi_tzawareness(self, other):
 | 
						|
        # GH#22074
 | 
						|
        # reversion test that we _don't_ call _assert_tzawareness_compat
 | 
						|
        # when comparing against TimedeltaIndex
 | 
						|
        dti = date_range("2000-01-01", periods=10, tz="Asia/Tokyo")
 | 
						|
 | 
						|
        result = dti == other
 | 
						|
        expected = np.array([False] * 10)
 | 
						|
        tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
        result = dti != other
 | 
						|
        expected = np.array([True] * 10)
 | 
						|
        tm.assert_numpy_array_equal(result, expected)
 | 
						|
        msg = "Invalid comparison between"
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            dti < other
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            dti <= other
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            dti > other
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            dti >= other
 | 
						|
 | 
						|
    def test_dti_cmp_object_dtype(self):
 | 
						|
        # GH#22074
 | 
						|
        dti = date_range("2000-01-01", periods=10, tz="Asia/Tokyo")
 | 
						|
 | 
						|
        other = dti.astype("O")
 | 
						|
 | 
						|
        result = dti == other
 | 
						|
        expected = np.array([True] * 10)
 | 
						|
        tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
        other = dti.tz_localize(None)
 | 
						|
        result = dti != other
 | 
						|
        tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
        other = np.array(list(dti[:5]) + [Timedelta(days=1)] * 5)
 | 
						|
        result = dti == other
 | 
						|
        expected = np.array([True] * 5 + [False] * 5)
 | 
						|
        tm.assert_numpy_array_equal(result, expected)
 | 
						|
        msg = ">=' not supported between instances of 'Timestamp' and 'Timedelta'"
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            dti >= other
 | 
						|
 | 
						|
 | 
						|
# ------------------------------------------------------------------
 | 
						|
# Arithmetic
 | 
						|
 | 
						|
 | 
						|
class TestDatetime64Arithmetic:
 | 
						|
    # This class is intended for "finished" tests that are fully parametrized
 | 
						|
    #  over DataFrame/Series/Index/DatetimeArray
 | 
						|
 | 
						|
    # -------------------------------------------------------------
 | 
						|
    # Addition/Subtraction of timedelta-like
 | 
						|
 | 
						|
    @pytest.mark.arm_slow
 | 
						|
    def test_dt64arr_add_timedeltalike_scalar(
 | 
						|
        self, tz_naive_fixture, two_hours, box_with_array
 | 
						|
    ):
 | 
						|
        # GH#22005, GH#22163 check DataFrame doesn't raise TypeError
 | 
						|
        tz = tz_naive_fixture
 | 
						|
 | 
						|
        rng = date_range("2000-01-01", "2000-02-01", tz=tz)
 | 
						|
        expected = date_range("2000-01-01 02:00", "2000-02-01 02:00", tz=tz)
 | 
						|
 | 
						|
        rng = tm.box_expected(rng, box_with_array)
 | 
						|
        expected = tm.box_expected(expected, box_with_array)
 | 
						|
 | 
						|
        result = rng + two_hours
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
 | 
						|
        result = two_hours + rng
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
 | 
						|
        rng += two_hours
 | 
						|
        tm.assert_equal(rng, expected)
 | 
						|
 | 
						|
    def test_dt64arr_sub_timedeltalike_scalar(
 | 
						|
        self, tz_naive_fixture, two_hours, box_with_array
 | 
						|
    ):
 | 
						|
        tz = tz_naive_fixture
 | 
						|
 | 
						|
        rng = date_range("2000-01-01", "2000-02-01", tz=tz)
 | 
						|
        expected = date_range("1999-12-31 22:00", "2000-01-31 22:00", tz=tz)
 | 
						|
 | 
						|
        rng = tm.box_expected(rng, box_with_array)
 | 
						|
        expected = tm.box_expected(expected, box_with_array)
 | 
						|
 | 
						|
        result = rng - two_hours
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
 | 
						|
        rng -= two_hours
 | 
						|
        tm.assert_equal(rng, expected)
 | 
						|
 | 
						|
    def test_dt64_array_sub_dt_with_different_timezone(self, box_with_array):
 | 
						|
        t1 = date_range("20130101", periods=3).tz_localize("US/Eastern")
 | 
						|
        t1 = tm.box_expected(t1, box_with_array)
 | 
						|
        t2 = Timestamp("20130101").tz_localize("CET")
 | 
						|
        tnaive = Timestamp(20130101)
 | 
						|
 | 
						|
        result = t1 - t2
 | 
						|
        expected = TimedeltaIndex(
 | 
						|
            ["0 days 06:00:00", "1 days 06:00:00", "2 days 06:00:00"]
 | 
						|
        )
 | 
						|
        expected = tm.box_expected(expected, box_with_array)
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
 | 
						|
        result = t2 - t1
 | 
						|
        expected = TimedeltaIndex(
 | 
						|
            ["-1 days +18:00:00", "-2 days +18:00:00", "-3 days +18:00:00"]
 | 
						|
        )
 | 
						|
        expected = tm.box_expected(expected, box_with_array)
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
 | 
						|
        msg = "Cannot subtract tz-naive and tz-aware datetime-like objects"
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            t1 - tnaive
 | 
						|
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            tnaive - t1
 | 
						|
 | 
						|
    def test_dt64_array_sub_dt64_array_with_different_timezone(self, box_with_array):
 | 
						|
        t1 = date_range("20130101", periods=3).tz_localize("US/Eastern")
 | 
						|
        t1 = tm.box_expected(t1, box_with_array)
 | 
						|
        t2 = date_range("20130101", periods=3).tz_localize("CET")
 | 
						|
        t2 = tm.box_expected(t2, box_with_array)
 | 
						|
        tnaive = date_range("20130101", periods=3)
 | 
						|
 | 
						|
        result = t1 - t2
 | 
						|
        expected = TimedeltaIndex(
 | 
						|
            ["0 days 06:00:00", "0 days 06:00:00", "0 days 06:00:00"]
 | 
						|
        )
 | 
						|
        expected = tm.box_expected(expected, box_with_array)
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
 | 
						|
        result = t2 - t1
 | 
						|
        expected = TimedeltaIndex(
 | 
						|
            ["-1 days +18:00:00", "-1 days +18:00:00", "-1 days +18:00:00"]
 | 
						|
        )
 | 
						|
        expected = tm.box_expected(expected, box_with_array)
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
 | 
						|
        msg = "Cannot subtract tz-naive and tz-aware datetime-like objects"
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            t1 - tnaive
 | 
						|
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            tnaive - t1
 | 
						|
 | 
						|
    def test_dt64arr_add_sub_td64_nat(self, box_with_array, tz_naive_fixture):
 | 
						|
        # GH#23320 special handling for timedelta64("NaT")
 | 
						|
        tz = tz_naive_fixture
 | 
						|
 | 
						|
        dti = date_range("1994-04-01", periods=9, tz=tz, freq="QS")
 | 
						|
        other = np.timedelta64("NaT")
 | 
						|
        expected = DatetimeIndex(["NaT"] * 9, tz=tz).as_unit("ns")
 | 
						|
 | 
						|
        obj = tm.box_expected(dti, box_with_array)
 | 
						|
        expected = tm.box_expected(expected, box_with_array)
 | 
						|
 | 
						|
        result = obj + other
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
        result = other + obj
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
        result = obj - other
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
        msg = "cannot subtract"
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            other - obj
 | 
						|
 | 
						|
    def test_dt64arr_add_sub_td64ndarray(self, tz_naive_fixture, box_with_array):
 | 
						|
        tz = tz_naive_fixture
 | 
						|
        dti = date_range("2016-01-01", periods=3, tz=tz)
 | 
						|
        tdi = TimedeltaIndex(["-1 Day", "-1 Day", "-1 Day"])
 | 
						|
        tdarr = tdi.values
 | 
						|
 | 
						|
        expected = date_range("2015-12-31", "2016-01-02", periods=3, tz=tz)
 | 
						|
 | 
						|
        dtarr = tm.box_expected(dti, box_with_array)
 | 
						|
        expected = tm.box_expected(expected, box_with_array)
 | 
						|
 | 
						|
        result = dtarr + tdarr
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
        result = tdarr + dtarr
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
 | 
						|
        expected = date_range("2016-01-02", "2016-01-04", periods=3, tz=tz)
 | 
						|
        expected = tm.box_expected(expected, box_with_array)
 | 
						|
 | 
						|
        result = dtarr - tdarr
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
        msg = "cannot subtract|(bad|unsupported) operand type for unary"
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            tdarr - dtarr
 | 
						|
 | 
						|
    # -----------------------------------------------------------------
 | 
						|
    # Subtraction of datetime-like scalars
 | 
						|
 | 
						|
    @pytest.mark.parametrize(
 | 
						|
        "ts",
 | 
						|
        [
 | 
						|
            Timestamp("2013-01-01"),
 | 
						|
            Timestamp("2013-01-01").to_pydatetime(),
 | 
						|
            Timestamp("2013-01-01").to_datetime64(),
 | 
						|
            # GH#7996, GH#22163 ensure non-nano datetime64 is converted to nano
 | 
						|
            #  for DataFrame operation
 | 
						|
            np.datetime64("2013-01-01", "D"),
 | 
						|
        ],
 | 
						|
    )
 | 
						|
    def test_dt64arr_sub_dtscalar(self, box_with_array, ts):
 | 
						|
        # GH#8554, GH#22163 DataFrame op should _not_ return dt64 dtype
 | 
						|
        idx = date_range("2013-01-01", periods=3)._with_freq(None)
 | 
						|
        idx = tm.box_expected(idx, box_with_array)
 | 
						|
 | 
						|
        expected = TimedeltaIndex(["0 Days", "1 Day", "2 Days"])
 | 
						|
        expected = tm.box_expected(expected, box_with_array)
 | 
						|
 | 
						|
        result = idx - ts
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
 | 
						|
        result = ts - idx
 | 
						|
        tm.assert_equal(result, -expected)
 | 
						|
        tm.assert_equal(result, -expected)
 | 
						|
 | 
						|
    def test_dt64arr_sub_timestamp_tzaware(self, box_with_array):
 | 
						|
        ser = date_range("2014-03-17", periods=2, freq="D", tz="US/Eastern")
 | 
						|
        ser = ser._with_freq(None)
 | 
						|
        ts = ser[0]
 | 
						|
 | 
						|
        ser = tm.box_expected(ser, box_with_array)
 | 
						|
 | 
						|
        delta_series = Series([np.timedelta64(0, "D"), np.timedelta64(1, "D")])
 | 
						|
        expected = tm.box_expected(delta_series, box_with_array)
 | 
						|
 | 
						|
        tm.assert_equal(ser - ts, expected)
 | 
						|
        tm.assert_equal(ts - ser, -expected)
 | 
						|
 | 
						|
    def test_dt64arr_sub_NaT(self, box_with_array, unit):
 | 
						|
        # GH#18808
 | 
						|
        dti = DatetimeIndex([NaT, Timestamp("19900315")]).as_unit(unit)
 | 
						|
        ser = tm.box_expected(dti, box_with_array)
 | 
						|
 | 
						|
        result = ser - NaT
 | 
						|
        expected = Series([NaT, NaT], dtype=f"timedelta64[{unit}]")
 | 
						|
        expected = tm.box_expected(expected, box_with_array)
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
 | 
						|
        dti_tz = dti.tz_localize("Asia/Tokyo")
 | 
						|
        ser_tz = tm.box_expected(dti_tz, box_with_array)
 | 
						|
 | 
						|
        result = ser_tz - NaT
 | 
						|
        expected = Series([NaT, NaT], dtype=f"timedelta64[{unit}]")
 | 
						|
        expected = tm.box_expected(expected, box_with_array)
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
 | 
						|
    # -------------------------------------------------------------
 | 
						|
    # Subtraction of datetime-like array-like
 | 
						|
 | 
						|
    def test_dt64arr_sub_dt64object_array(self, box_with_array, tz_naive_fixture):
 | 
						|
        dti = date_range("2016-01-01", periods=3, tz=tz_naive_fixture)
 | 
						|
        expected = dti - dti
 | 
						|
 | 
						|
        obj = tm.box_expected(dti, box_with_array)
 | 
						|
        expected = tm.box_expected(expected, box_with_array).astype(object)
 | 
						|
 | 
						|
        with tm.assert_produces_warning(PerformanceWarning):
 | 
						|
            result = obj - obj.astype(object)
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
 | 
						|
    def test_dt64arr_naive_sub_dt64ndarray(self, box_with_array):
 | 
						|
        dti = date_range("2016-01-01", periods=3, tz=None)
 | 
						|
        dt64vals = dti.values
 | 
						|
 | 
						|
        dtarr = tm.box_expected(dti, box_with_array)
 | 
						|
 | 
						|
        expected = dtarr - dtarr
 | 
						|
        result = dtarr - dt64vals
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
        result = dt64vals - dtarr
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
 | 
						|
    def test_dt64arr_aware_sub_dt64ndarray_raises(
 | 
						|
        self, tz_aware_fixture, box_with_array
 | 
						|
    ):
 | 
						|
        tz = tz_aware_fixture
 | 
						|
        dti = date_range("2016-01-01", periods=3, tz=tz)
 | 
						|
        dt64vals = dti.values
 | 
						|
 | 
						|
        dtarr = tm.box_expected(dti, box_with_array)
 | 
						|
        msg = "Cannot subtract tz-naive and tz-aware datetime"
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            dtarr - dt64vals
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            dt64vals - dtarr
 | 
						|
 | 
						|
    # -------------------------------------------------------------
 | 
						|
    # Addition of datetime-like others (invalid)
 | 
						|
 | 
						|
    def test_dt64arr_add_dtlike_raises(self, tz_naive_fixture, box_with_array):
 | 
						|
        # GH#22163 ensure DataFrame doesn't cast Timestamp to i8
 | 
						|
        # GH#9631
 | 
						|
        tz = tz_naive_fixture
 | 
						|
 | 
						|
        dti = date_range("2016-01-01", periods=3, tz=tz)
 | 
						|
        if tz is None:
 | 
						|
            dti2 = dti.tz_localize("US/Eastern")
 | 
						|
        else:
 | 
						|
            dti2 = dti.tz_localize(None)
 | 
						|
        dtarr = tm.box_expected(dti, box_with_array)
 | 
						|
 | 
						|
        assert_cannot_add(dtarr, dti.values)
 | 
						|
        assert_cannot_add(dtarr, dti)
 | 
						|
        assert_cannot_add(dtarr, dtarr)
 | 
						|
        assert_cannot_add(dtarr, dti[0])
 | 
						|
        assert_cannot_add(dtarr, dti[0].to_pydatetime())
 | 
						|
        assert_cannot_add(dtarr, dti[0].to_datetime64())
 | 
						|
        assert_cannot_add(dtarr, dti2[0])
 | 
						|
        assert_cannot_add(dtarr, dti2[0].to_pydatetime())
 | 
						|
        assert_cannot_add(dtarr, np.datetime64("2011-01-01", "D"))
 | 
						|
 | 
						|
    # -------------------------------------------------------------
 | 
						|
    # Other Invalid Addition/Subtraction
 | 
						|
 | 
						|
    # Note: freq here includes both Tick and non-Tick offsets; this is
 | 
						|
    #  relevant because historically integer-addition was allowed if we had
 | 
						|
    #  a freq.
 | 
						|
    @pytest.mark.parametrize("freq", ["h", "D", "W", "2ME", "MS", "QE", "B", None])
 | 
						|
    @pytest.mark.parametrize("dtype", [None, "uint8"])
 | 
						|
    def test_dt64arr_addsub_intlike(
 | 
						|
        self, request, dtype, index_or_series_or_array, freq, tz_naive_fixture
 | 
						|
    ):
 | 
						|
        # GH#19959, GH#19123, GH#19012
 | 
						|
        # GH#55860 use index_or_series_or_array instead of box_with_array
 | 
						|
        #  bc DataFrame alignment makes it inapplicable
 | 
						|
        tz = tz_naive_fixture
 | 
						|
 | 
						|
        if freq is None:
 | 
						|
            dti = DatetimeIndex(["NaT", "2017-04-05 06:07:08"], tz=tz)
 | 
						|
        else:
 | 
						|
            dti = date_range("2016-01-01", periods=2, freq=freq, tz=tz)
 | 
						|
 | 
						|
        obj = index_or_series_or_array(dti)
 | 
						|
        other = np.array([4, -1])
 | 
						|
        if dtype is not None:
 | 
						|
            other = other.astype(dtype)
 | 
						|
 | 
						|
        msg = "|".join(
 | 
						|
            [
 | 
						|
                "Addition/subtraction of integers",
 | 
						|
                "cannot subtract DatetimeArray from",
 | 
						|
                # IntegerArray
 | 
						|
                "can only perform ops with numeric values",
 | 
						|
                "unsupported operand type.*Categorical",
 | 
						|
                r"unsupported operand type\(s\) for -: 'int' and 'Timestamp'",
 | 
						|
            ]
 | 
						|
        )
 | 
						|
        assert_invalid_addsub_type(obj, 1, msg)
 | 
						|
        assert_invalid_addsub_type(obj, np.int64(2), msg)
 | 
						|
        assert_invalid_addsub_type(obj, np.array(3, dtype=np.int64), msg)
 | 
						|
        assert_invalid_addsub_type(obj, other, msg)
 | 
						|
        assert_invalid_addsub_type(obj, np.array(other), msg)
 | 
						|
        assert_invalid_addsub_type(obj, pd.array(other), msg)
 | 
						|
        assert_invalid_addsub_type(obj, pd.Categorical(other), msg)
 | 
						|
        assert_invalid_addsub_type(obj, pd.Index(other), msg)
 | 
						|
        assert_invalid_addsub_type(obj, Series(other), msg)
 | 
						|
 | 
						|
    @pytest.mark.parametrize(
 | 
						|
        "other",
 | 
						|
        [
 | 
						|
            3.14,
 | 
						|
            np.array([2.0, 3.0]),
 | 
						|
            # GH#13078 datetime +/- Period is invalid
 | 
						|
            Period("2011-01-01", freq="D"),
 | 
						|
            # https://github.com/pandas-dev/pandas/issues/10329
 | 
						|
            time(1, 2, 3),
 | 
						|
        ],
 | 
						|
    )
 | 
						|
    @pytest.mark.parametrize("dti_freq", [None, "D"])
 | 
						|
    def test_dt64arr_add_sub_invalid(self, dti_freq, other, box_with_array):
 | 
						|
        dti = DatetimeIndex(["2011-01-01", "2011-01-02"], freq=dti_freq)
 | 
						|
        dtarr = tm.box_expected(dti, box_with_array)
 | 
						|
        msg = "|".join(
 | 
						|
            [
 | 
						|
                "unsupported operand type",
 | 
						|
                "cannot (add|subtract)",
 | 
						|
                "cannot use operands with types",
 | 
						|
                "ufunc '?(add|subtract)'? cannot use operands with types",
 | 
						|
                "Concatenation operation is not implemented for NumPy arrays",
 | 
						|
            ]
 | 
						|
        )
 | 
						|
        assert_invalid_addsub_type(dtarr, other, msg)
 | 
						|
 | 
						|
    @pytest.mark.parametrize("pi_freq", ["D", "W", "Q", "h"])
 | 
						|
    @pytest.mark.parametrize("dti_freq", [None, "D"])
 | 
						|
    def test_dt64arr_add_sub_parr(
 | 
						|
        self, dti_freq, pi_freq, box_with_array, box_with_array2
 | 
						|
    ):
 | 
						|
        # GH#20049 subtracting PeriodIndex should raise TypeError
 | 
						|
        dti = DatetimeIndex(["2011-01-01", "2011-01-02"], freq=dti_freq)
 | 
						|
        pi = dti.to_period(pi_freq)
 | 
						|
 | 
						|
        dtarr = tm.box_expected(dti, box_with_array)
 | 
						|
        parr = tm.box_expected(pi, box_with_array2)
 | 
						|
        msg = "|".join(
 | 
						|
            [
 | 
						|
                "cannot (add|subtract)",
 | 
						|
                "unsupported operand",
 | 
						|
                "descriptor.*requires",
 | 
						|
                "ufunc.*cannot use operands",
 | 
						|
            ]
 | 
						|
        )
 | 
						|
        assert_invalid_addsub_type(dtarr, parr, msg)
 | 
						|
 | 
						|
    @pytest.mark.filterwarnings("ignore::pandas.errors.PerformanceWarning")
 | 
						|
    def test_dt64arr_addsub_time_objects_raises(self, box_with_array, tz_naive_fixture):
 | 
						|
        # https://github.com/pandas-dev/pandas/issues/10329
 | 
						|
 | 
						|
        tz = tz_naive_fixture
 | 
						|
 | 
						|
        obj1 = date_range("2012-01-01", periods=3, tz=tz)
 | 
						|
        obj2 = [time(i, i, i) for i in range(3)]
 | 
						|
 | 
						|
        obj1 = tm.box_expected(obj1, box_with_array)
 | 
						|
        obj2 = tm.box_expected(obj2, box_with_array)
 | 
						|
 | 
						|
        msg = "|".join(
 | 
						|
            [
 | 
						|
                "unsupported operand",
 | 
						|
                "cannot subtract DatetimeArray from ndarray",
 | 
						|
            ]
 | 
						|
        )
 | 
						|
        # pandas.errors.PerformanceWarning: Non-vectorized DateOffset being
 | 
						|
        # applied to Series or DatetimeIndex
 | 
						|
        # we aren't testing that here, so ignore.
 | 
						|
        assert_invalid_addsub_type(obj1, obj2, msg=msg)
 | 
						|
 | 
						|
    # -------------------------------------------------------------
 | 
						|
    # Other invalid operations
 | 
						|
 | 
						|
    @pytest.mark.parametrize(
 | 
						|
        "dt64_series",
 | 
						|
        [
 | 
						|
            Series([Timestamp("19900315"), Timestamp("19900315")]),
 | 
						|
            Series([NaT, Timestamp("19900315")]),
 | 
						|
            Series([NaT, NaT], dtype="datetime64[ns]"),
 | 
						|
        ],
 | 
						|
    )
 | 
						|
    @pytest.mark.parametrize("one", [1, 1.0, np.array(1)])
 | 
						|
    def test_dt64_mul_div_numeric_invalid(self, one, dt64_series, box_with_array):
 | 
						|
        obj = tm.box_expected(dt64_series, box_with_array)
 | 
						|
 | 
						|
        msg = "cannot perform .* with this index type"
 | 
						|
 | 
						|
        # multiplication
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            obj * one
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            one * obj
 | 
						|
 | 
						|
        # division
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            obj / one
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            one / obj
 | 
						|
 | 
						|
 | 
						|
class TestDatetime64DateOffsetArithmetic:
 | 
						|
    # -------------------------------------------------------------
 | 
						|
    # Tick DateOffsets
 | 
						|
 | 
						|
    # TODO: parametrize over timezone?
 | 
						|
    @pytest.mark.parametrize("unit", ["s", "ms", "us", "ns"])
 | 
						|
    def test_dt64arr_series_add_tick_DateOffset(self, box_with_array, unit):
 | 
						|
        # GH#4532
 | 
						|
        # operate with pd.offsets
 | 
						|
        ser = Series(
 | 
						|
            [Timestamp("20130101 9:01"), Timestamp("20130101 9:02")]
 | 
						|
        ).dt.as_unit(unit)
 | 
						|
        expected = Series(
 | 
						|
            [Timestamp("20130101 9:01:05"), Timestamp("20130101 9:02:05")]
 | 
						|
        ).dt.as_unit(unit)
 | 
						|
 | 
						|
        ser = tm.box_expected(ser, box_with_array)
 | 
						|
        expected = tm.box_expected(expected, box_with_array)
 | 
						|
 | 
						|
        result = ser + pd.offsets.Second(5)
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
 | 
						|
        result2 = pd.offsets.Second(5) + ser
 | 
						|
        tm.assert_equal(result2, expected)
 | 
						|
 | 
						|
    def test_dt64arr_series_sub_tick_DateOffset(self, box_with_array):
 | 
						|
        # GH#4532
 | 
						|
        # operate with pd.offsets
 | 
						|
        ser = Series([Timestamp("20130101 9:01"), Timestamp("20130101 9:02")])
 | 
						|
        expected = Series(
 | 
						|
            [Timestamp("20130101 9:00:55"), Timestamp("20130101 9:01:55")]
 | 
						|
        )
 | 
						|
 | 
						|
        ser = tm.box_expected(ser, box_with_array)
 | 
						|
        expected = tm.box_expected(expected, box_with_array)
 | 
						|
 | 
						|
        result = ser - pd.offsets.Second(5)
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
 | 
						|
        result2 = -pd.offsets.Second(5) + ser
 | 
						|
        tm.assert_equal(result2, expected)
 | 
						|
        msg = "(bad|unsupported) operand type for unary"
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            pd.offsets.Second(5) - ser
 | 
						|
 | 
						|
    @pytest.mark.parametrize(
 | 
						|
        "cls_name", ["Day", "Hour", "Minute", "Second", "Milli", "Micro", "Nano"]
 | 
						|
    )
 | 
						|
    def test_dt64arr_add_sub_tick_DateOffset_smoke(self, cls_name, box_with_array):
 | 
						|
        # GH#4532
 | 
						|
        # smoke tests for valid DateOffsets
 | 
						|
        ser = Series([Timestamp("20130101 9:01"), Timestamp("20130101 9:02")])
 | 
						|
        ser = tm.box_expected(ser, box_with_array)
 | 
						|
 | 
						|
        offset_cls = getattr(pd.offsets, cls_name)
 | 
						|
        ser + offset_cls(5)
 | 
						|
        offset_cls(5) + ser
 | 
						|
        ser - offset_cls(5)
 | 
						|
 | 
						|
    def test_dti_add_tick_tzaware(self, tz_aware_fixture, box_with_array):
 | 
						|
        # GH#21610, GH#22163 ensure DataFrame doesn't return object-dtype
 | 
						|
        tz = tz_aware_fixture
 | 
						|
        if tz == "US/Pacific":
 | 
						|
            dates = date_range("2012-11-01", periods=3, tz=tz)
 | 
						|
            offset = dates + pd.offsets.Hour(5)
 | 
						|
            assert dates[0] + pd.offsets.Hour(5) == offset[0]
 | 
						|
 | 
						|
        dates = date_range("2010-11-01 00:00", periods=3, tz=tz, freq="h")
 | 
						|
        expected = DatetimeIndex(
 | 
						|
            ["2010-11-01 05:00", "2010-11-01 06:00", "2010-11-01 07:00"],
 | 
						|
            freq="h",
 | 
						|
            tz=tz,
 | 
						|
        ).as_unit("ns")
 | 
						|
 | 
						|
        dates = tm.box_expected(dates, box_with_array)
 | 
						|
        expected = tm.box_expected(expected, box_with_array)
 | 
						|
 | 
						|
        for scalar in [pd.offsets.Hour(5), np.timedelta64(5, "h"), timedelta(hours=5)]:
 | 
						|
            offset = dates + scalar
 | 
						|
            tm.assert_equal(offset, expected)
 | 
						|
            offset = scalar + dates
 | 
						|
            tm.assert_equal(offset, expected)
 | 
						|
 | 
						|
            roundtrip = offset - scalar
 | 
						|
            tm.assert_equal(roundtrip, dates)
 | 
						|
 | 
						|
            msg = "|".join(
 | 
						|
                ["bad operand type for unary -", "cannot subtract DatetimeArray"]
 | 
						|
            )
 | 
						|
            with pytest.raises(TypeError, match=msg):
 | 
						|
                scalar - dates
 | 
						|
 | 
						|
    # -------------------------------------------------------------
 | 
						|
    # RelativeDelta DateOffsets
 | 
						|
 | 
						|
    @pytest.mark.parametrize("unit", ["s", "ms", "us", "ns"])
 | 
						|
    def test_dt64arr_add_sub_relativedelta_offsets(self, box_with_array, unit):
 | 
						|
        # GH#10699
 | 
						|
        vec = DatetimeIndex(
 | 
						|
            [
 | 
						|
                Timestamp("2000-01-05 00:15:00"),
 | 
						|
                Timestamp("2000-01-31 00:23:00"),
 | 
						|
                Timestamp("2000-01-01"),
 | 
						|
                Timestamp("2000-03-31"),
 | 
						|
                Timestamp("2000-02-29"),
 | 
						|
                Timestamp("2000-12-31"),
 | 
						|
                Timestamp("2000-05-15"),
 | 
						|
                Timestamp("2001-06-15"),
 | 
						|
            ]
 | 
						|
        ).as_unit(unit)
 | 
						|
        vec = tm.box_expected(vec, box_with_array)
 | 
						|
        vec_items = vec.iloc[0] if box_with_array is pd.DataFrame else vec
 | 
						|
 | 
						|
        # DateOffset relativedelta fastpath
 | 
						|
        relative_kwargs = [
 | 
						|
            ("years", 2),
 | 
						|
            ("months", 5),
 | 
						|
            ("days", 3),
 | 
						|
            ("hours", 5),
 | 
						|
            ("minutes", 10),
 | 
						|
            ("seconds", 2),
 | 
						|
            ("microseconds", 5),
 | 
						|
        ]
 | 
						|
        for i, (offset_unit, value) in enumerate(relative_kwargs):
 | 
						|
            off = DateOffset(**{offset_unit: value})
 | 
						|
 | 
						|
            exp_unit = unit
 | 
						|
            if offset_unit == "microseconds" and unit != "ns":
 | 
						|
                exp_unit = "us"
 | 
						|
 | 
						|
            # TODO(GH#55564): as_unit will be unnecessary
 | 
						|
            expected = DatetimeIndex([x + off for x in vec_items]).as_unit(exp_unit)
 | 
						|
            expected = tm.box_expected(expected, box_with_array)
 | 
						|
            tm.assert_equal(expected, vec + off)
 | 
						|
 | 
						|
            expected = DatetimeIndex([x - off for x in vec_items]).as_unit(exp_unit)
 | 
						|
            expected = tm.box_expected(expected, box_with_array)
 | 
						|
            tm.assert_equal(expected, vec - off)
 | 
						|
 | 
						|
            off = DateOffset(**dict(relative_kwargs[: i + 1]))
 | 
						|
 | 
						|
            expected = DatetimeIndex([x + off for x in vec_items]).as_unit(exp_unit)
 | 
						|
            expected = tm.box_expected(expected, box_with_array)
 | 
						|
            tm.assert_equal(expected, vec + off)
 | 
						|
 | 
						|
            expected = DatetimeIndex([x - off for x in vec_items]).as_unit(exp_unit)
 | 
						|
            expected = tm.box_expected(expected, box_with_array)
 | 
						|
            tm.assert_equal(expected, vec - off)
 | 
						|
            msg = "(bad|unsupported) operand type for unary"
 | 
						|
            with pytest.raises(TypeError, match=msg):
 | 
						|
                off - vec
 | 
						|
 | 
						|
    # -------------------------------------------------------------
 | 
						|
    # Non-Tick, Non-RelativeDelta DateOffsets
 | 
						|
 | 
						|
    # TODO: redundant with test_dt64arr_add_sub_DateOffset?  that includes
 | 
						|
    #  tz-aware cases which this does not
 | 
						|
    @pytest.mark.filterwarnings("ignore::pandas.errors.PerformanceWarning")
 | 
						|
    @pytest.mark.parametrize(
 | 
						|
        "cls_and_kwargs",
 | 
						|
        [
 | 
						|
            "YearBegin",
 | 
						|
            ("YearBegin", {"month": 5}),
 | 
						|
            "YearEnd",
 | 
						|
            ("YearEnd", {"month": 5}),
 | 
						|
            "MonthBegin",
 | 
						|
            "MonthEnd",
 | 
						|
            "SemiMonthEnd",
 | 
						|
            "SemiMonthBegin",
 | 
						|
            "Week",
 | 
						|
            ("Week", {"weekday": 3}),
 | 
						|
            "Week",
 | 
						|
            ("Week", {"weekday": 6}),
 | 
						|
            "BusinessDay",
 | 
						|
            "BDay",
 | 
						|
            "QuarterEnd",
 | 
						|
            "QuarterBegin",
 | 
						|
            "CustomBusinessDay",
 | 
						|
            "CDay",
 | 
						|
            "CBMonthEnd",
 | 
						|
            "CBMonthBegin",
 | 
						|
            "BMonthBegin",
 | 
						|
            "BMonthEnd",
 | 
						|
            "BusinessHour",
 | 
						|
            "BYearBegin",
 | 
						|
            "BYearEnd",
 | 
						|
            "BQuarterBegin",
 | 
						|
            ("LastWeekOfMonth", {"weekday": 2}),
 | 
						|
            (
 | 
						|
                "FY5253Quarter",
 | 
						|
                {
 | 
						|
                    "qtr_with_extra_week": 1,
 | 
						|
                    "startingMonth": 1,
 | 
						|
                    "weekday": 2,
 | 
						|
                    "variation": "nearest",
 | 
						|
                },
 | 
						|
            ),
 | 
						|
            ("FY5253", {"weekday": 0, "startingMonth": 2, "variation": "nearest"}),
 | 
						|
            ("WeekOfMonth", {"weekday": 2, "week": 2}),
 | 
						|
            "Easter",
 | 
						|
            ("DateOffset", {"day": 4}),
 | 
						|
            ("DateOffset", {"month": 5}),
 | 
						|
        ],
 | 
						|
    )
 | 
						|
    @pytest.mark.parametrize("normalize", [True, False])
 | 
						|
    @pytest.mark.parametrize("n", [0, 5])
 | 
						|
    @pytest.mark.parametrize("unit", ["s", "ms", "us", "ns"])
 | 
						|
    @pytest.mark.parametrize("tz", [None, "US/Central"])
 | 
						|
    def test_dt64arr_add_sub_DateOffsets(
 | 
						|
        self, box_with_array, n, normalize, cls_and_kwargs, unit, tz
 | 
						|
    ):
 | 
						|
        # GH#10699
 | 
						|
        # assert vectorized operation matches pointwise operations
 | 
						|
 | 
						|
        if isinstance(cls_and_kwargs, tuple):
 | 
						|
            # If cls_name param is a tuple, then 2nd entry is kwargs for
 | 
						|
            # the offset constructor
 | 
						|
            cls_name, kwargs = cls_and_kwargs
 | 
						|
        else:
 | 
						|
            cls_name = cls_and_kwargs
 | 
						|
            kwargs = {}
 | 
						|
 | 
						|
        if n == 0 and cls_name in [
 | 
						|
            "WeekOfMonth",
 | 
						|
            "LastWeekOfMonth",
 | 
						|
            "FY5253Quarter",
 | 
						|
            "FY5253",
 | 
						|
        ]:
 | 
						|
            # passing n = 0 is invalid for these offset classes
 | 
						|
            return
 | 
						|
 | 
						|
        vec = (
 | 
						|
            DatetimeIndex(
 | 
						|
                [
 | 
						|
                    Timestamp("2000-01-05 00:15:00"),
 | 
						|
                    Timestamp("2000-01-31 00:23:00"),
 | 
						|
                    Timestamp("2000-01-01"),
 | 
						|
                    Timestamp("2000-03-31"),
 | 
						|
                    Timestamp("2000-02-29"),
 | 
						|
                    Timestamp("2000-12-31"),
 | 
						|
                    Timestamp("2000-05-15"),
 | 
						|
                    Timestamp("2001-06-15"),
 | 
						|
                ]
 | 
						|
            )
 | 
						|
            .as_unit(unit)
 | 
						|
            .tz_localize(tz)
 | 
						|
        )
 | 
						|
        vec = tm.box_expected(vec, box_with_array)
 | 
						|
        vec_items = vec.iloc[0] if box_with_array is pd.DataFrame else vec
 | 
						|
 | 
						|
        offset_cls = getattr(pd.offsets, cls_name)
 | 
						|
        offset = offset_cls(n, normalize=normalize, **kwargs)
 | 
						|
 | 
						|
        # TODO(GH#55564): as_unit will be unnecessary
 | 
						|
        expected = DatetimeIndex([x + offset for x in vec_items]).as_unit(unit)
 | 
						|
        expected = tm.box_expected(expected, box_with_array)
 | 
						|
        tm.assert_equal(expected, vec + offset)
 | 
						|
        tm.assert_equal(expected, offset + vec)
 | 
						|
 | 
						|
        expected = DatetimeIndex([x - offset for x in vec_items]).as_unit(unit)
 | 
						|
        expected = tm.box_expected(expected, box_with_array)
 | 
						|
        tm.assert_equal(expected, vec - offset)
 | 
						|
 | 
						|
        expected = DatetimeIndex([offset + x for x in vec_items]).as_unit(unit)
 | 
						|
        expected = tm.box_expected(expected, box_with_array)
 | 
						|
        tm.assert_equal(expected, offset + vec)
 | 
						|
        msg = "(bad|unsupported) operand type for unary"
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            offset - vec
 | 
						|
 | 
						|
    @pytest.mark.parametrize(
 | 
						|
        "other",
 | 
						|
        [
 | 
						|
            np.array([pd.offsets.MonthEnd(), pd.offsets.Day(n=2)]),
 | 
						|
            np.array([pd.offsets.DateOffset(years=1), pd.offsets.MonthEnd()]),
 | 
						|
            np.array(  # matching offsets
 | 
						|
                [pd.offsets.DateOffset(years=1), pd.offsets.DateOffset(years=1)]
 | 
						|
            ),
 | 
						|
        ],
 | 
						|
    )
 | 
						|
    @pytest.mark.parametrize("op", [operator.add, roperator.radd, operator.sub])
 | 
						|
    def test_dt64arr_add_sub_offset_array(
 | 
						|
        self, tz_naive_fixture, box_with_array, op, other
 | 
						|
    ):
 | 
						|
        # GH#18849
 | 
						|
        # GH#10699 array of offsets
 | 
						|
 | 
						|
        tz = tz_naive_fixture
 | 
						|
        dti = date_range("2017-01-01", periods=2, tz=tz)
 | 
						|
        dtarr = tm.box_expected(dti, box_with_array)
 | 
						|
 | 
						|
        expected = DatetimeIndex([op(dti[n], other[n]) for n in range(len(dti))])
 | 
						|
        expected = tm.box_expected(expected, box_with_array).astype(object)
 | 
						|
 | 
						|
        with tm.assert_produces_warning(PerformanceWarning):
 | 
						|
            res = op(dtarr, other)
 | 
						|
        tm.assert_equal(res, expected)
 | 
						|
 | 
						|
        # Same thing but boxing other
 | 
						|
        other = tm.box_expected(other, box_with_array)
 | 
						|
        if box_with_array is pd.array and op is roperator.radd:
 | 
						|
            # We expect a NumpyExtensionArray, not ndarray[object] here
 | 
						|
            expected = pd.array(expected, dtype=object)
 | 
						|
        with tm.assert_produces_warning(PerformanceWarning):
 | 
						|
            res = op(dtarr, other)
 | 
						|
        tm.assert_equal(res, expected)
 | 
						|
 | 
						|
    @pytest.mark.parametrize(
 | 
						|
        "op, offset, exp, exp_freq",
 | 
						|
        [
 | 
						|
            (
 | 
						|
                "__add__",
 | 
						|
                DateOffset(months=3, days=10),
 | 
						|
                [
 | 
						|
                    Timestamp("2014-04-11"),
 | 
						|
                    Timestamp("2015-04-11"),
 | 
						|
                    Timestamp("2016-04-11"),
 | 
						|
                    Timestamp("2017-04-11"),
 | 
						|
                ],
 | 
						|
                None,
 | 
						|
            ),
 | 
						|
            (
 | 
						|
                "__add__",
 | 
						|
                DateOffset(months=3),
 | 
						|
                [
 | 
						|
                    Timestamp("2014-04-01"),
 | 
						|
                    Timestamp("2015-04-01"),
 | 
						|
                    Timestamp("2016-04-01"),
 | 
						|
                    Timestamp("2017-04-01"),
 | 
						|
                ],
 | 
						|
                "YS-APR",
 | 
						|
            ),
 | 
						|
            (
 | 
						|
                "__sub__",
 | 
						|
                DateOffset(months=3, days=10),
 | 
						|
                [
 | 
						|
                    Timestamp("2013-09-21"),
 | 
						|
                    Timestamp("2014-09-21"),
 | 
						|
                    Timestamp("2015-09-21"),
 | 
						|
                    Timestamp("2016-09-21"),
 | 
						|
                ],
 | 
						|
                None,
 | 
						|
            ),
 | 
						|
            (
 | 
						|
                "__sub__",
 | 
						|
                DateOffset(months=3),
 | 
						|
                [
 | 
						|
                    Timestamp("2013-10-01"),
 | 
						|
                    Timestamp("2014-10-01"),
 | 
						|
                    Timestamp("2015-10-01"),
 | 
						|
                    Timestamp("2016-10-01"),
 | 
						|
                ],
 | 
						|
                "YS-OCT",
 | 
						|
            ),
 | 
						|
        ],
 | 
						|
    )
 | 
						|
    def test_dti_add_sub_nonzero_mth_offset(
 | 
						|
        self, op, offset, exp, exp_freq, tz_aware_fixture, box_with_array
 | 
						|
    ):
 | 
						|
        # GH 26258
 | 
						|
        tz = tz_aware_fixture
 | 
						|
        date = date_range(start="01 Jan 2014", end="01 Jan 2017", freq="YS", tz=tz)
 | 
						|
        date = tm.box_expected(date, box_with_array, False)
 | 
						|
        mth = getattr(date, op)
 | 
						|
        result = mth(offset)
 | 
						|
 | 
						|
        expected = DatetimeIndex(exp, tz=tz).as_unit("ns")
 | 
						|
        expected = tm.box_expected(expected, box_with_array, False)
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
 | 
						|
    def test_dt64arr_series_add_DateOffset_with_milli(self):
 | 
						|
        # GH 57529
 | 
						|
        dti = DatetimeIndex(
 | 
						|
            [
 | 
						|
                "2000-01-01 00:00:00.012345678",
 | 
						|
                "2000-01-31 00:00:00.012345678",
 | 
						|
                "2000-02-29 00:00:00.012345678",
 | 
						|
            ],
 | 
						|
            dtype="datetime64[ns]",
 | 
						|
        )
 | 
						|
        result = dti + DateOffset(milliseconds=4)
 | 
						|
        expected = DatetimeIndex(
 | 
						|
            [
 | 
						|
                "2000-01-01 00:00:00.016345678",
 | 
						|
                "2000-01-31 00:00:00.016345678",
 | 
						|
                "2000-02-29 00:00:00.016345678",
 | 
						|
            ],
 | 
						|
            dtype="datetime64[ns]",
 | 
						|
        )
 | 
						|
        tm.assert_index_equal(result, expected)
 | 
						|
 | 
						|
        result = dti + DateOffset(days=1, milliseconds=4)
 | 
						|
        expected = DatetimeIndex(
 | 
						|
            [
 | 
						|
                "2000-01-02 00:00:00.016345678",
 | 
						|
                "2000-02-01 00:00:00.016345678",
 | 
						|
                "2000-03-01 00:00:00.016345678",
 | 
						|
            ],
 | 
						|
            dtype="datetime64[ns]",
 | 
						|
        )
 | 
						|
        tm.assert_index_equal(result, expected)
 | 
						|
 | 
						|
 | 
						|
class TestDatetime64OverflowHandling:
 | 
						|
    # TODO: box + de-duplicate
 | 
						|
 | 
						|
    def test_dt64_overflow_masking(self, box_with_array):
 | 
						|
        # GH#25317
 | 
						|
        left = Series([Timestamp("1969-12-31")], dtype="M8[ns]")
 | 
						|
        right = Series([NaT])
 | 
						|
 | 
						|
        left = tm.box_expected(left, box_with_array)
 | 
						|
        right = tm.box_expected(right, box_with_array)
 | 
						|
 | 
						|
        expected = TimedeltaIndex([NaT], dtype="m8[ns]")
 | 
						|
        expected = tm.box_expected(expected, box_with_array)
 | 
						|
 | 
						|
        result = left - right
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
 | 
						|
    def test_dt64_series_arith_overflow(self):
 | 
						|
        # GH#12534, fixed by GH#19024
 | 
						|
        dt = Timestamp("1700-01-31")
 | 
						|
        td = Timedelta("20000 Days")
 | 
						|
        dti = date_range("1949-09-30", freq="100YE", periods=4)
 | 
						|
        ser = Series(dti)
 | 
						|
        msg = "Overflow in int64 addition"
 | 
						|
        with pytest.raises(OverflowError, match=msg):
 | 
						|
            ser - dt
 | 
						|
        with pytest.raises(OverflowError, match=msg):
 | 
						|
            dt - ser
 | 
						|
        with pytest.raises(OverflowError, match=msg):
 | 
						|
            ser + td
 | 
						|
        with pytest.raises(OverflowError, match=msg):
 | 
						|
            td + ser
 | 
						|
 | 
						|
        ser.iloc[-1] = NaT
 | 
						|
        expected = Series(
 | 
						|
            ["2004-10-03", "2104-10-04", "2204-10-04", "NaT"], dtype="datetime64[ns]"
 | 
						|
        )
 | 
						|
        res = ser + td
 | 
						|
        tm.assert_series_equal(res, expected)
 | 
						|
        res = td + ser
 | 
						|
        tm.assert_series_equal(res, expected)
 | 
						|
 | 
						|
        ser.iloc[1:] = NaT
 | 
						|
        expected = Series(["91279 Days", "NaT", "NaT", "NaT"], dtype="timedelta64[ns]")
 | 
						|
        res = ser - dt
 | 
						|
        tm.assert_series_equal(res, expected)
 | 
						|
        res = dt - ser
 | 
						|
        tm.assert_series_equal(res, -expected)
 | 
						|
 | 
						|
    def test_datetimeindex_sub_timestamp_overflow(self):
 | 
						|
        dtimax = pd.to_datetime(["2021-12-28 17:19", Timestamp.max]).as_unit("ns")
 | 
						|
        dtimin = pd.to_datetime(["2021-12-28 17:19", Timestamp.min]).as_unit("ns")
 | 
						|
 | 
						|
        tsneg = Timestamp("1950-01-01").as_unit("ns")
 | 
						|
        ts_neg_variants = [
 | 
						|
            tsneg,
 | 
						|
            tsneg.to_pydatetime(),
 | 
						|
            tsneg.to_datetime64().astype("datetime64[ns]"),
 | 
						|
            tsneg.to_datetime64().astype("datetime64[D]"),
 | 
						|
        ]
 | 
						|
 | 
						|
        tspos = Timestamp("1980-01-01").as_unit("ns")
 | 
						|
        ts_pos_variants = [
 | 
						|
            tspos,
 | 
						|
            tspos.to_pydatetime(),
 | 
						|
            tspos.to_datetime64().astype("datetime64[ns]"),
 | 
						|
            tspos.to_datetime64().astype("datetime64[D]"),
 | 
						|
        ]
 | 
						|
        msg = "Overflow in int64 addition"
 | 
						|
        for variant in ts_neg_variants:
 | 
						|
            with pytest.raises(OverflowError, match=msg):
 | 
						|
                dtimax - variant
 | 
						|
 | 
						|
        expected = Timestamp.max._value - tspos._value
 | 
						|
        for variant in ts_pos_variants:
 | 
						|
            res = dtimax - variant
 | 
						|
            assert res[1]._value == expected
 | 
						|
 | 
						|
        expected = Timestamp.min._value - tsneg._value
 | 
						|
        for variant in ts_neg_variants:
 | 
						|
            res = dtimin - variant
 | 
						|
            assert res[1]._value == expected
 | 
						|
 | 
						|
        for variant in ts_pos_variants:
 | 
						|
            with pytest.raises(OverflowError, match=msg):
 | 
						|
                dtimin - variant
 | 
						|
 | 
						|
    def test_datetimeindex_sub_datetimeindex_overflow(self):
 | 
						|
        # GH#22492, GH#22508
 | 
						|
        dtimax = pd.to_datetime(["2021-12-28 17:19", Timestamp.max]).as_unit("ns")
 | 
						|
        dtimin = pd.to_datetime(["2021-12-28 17:19", Timestamp.min]).as_unit("ns")
 | 
						|
 | 
						|
        ts_neg = pd.to_datetime(["1950-01-01", "1950-01-01"]).as_unit("ns")
 | 
						|
        ts_pos = pd.to_datetime(["1980-01-01", "1980-01-01"]).as_unit("ns")
 | 
						|
 | 
						|
        # General tests
 | 
						|
        expected = Timestamp.max._value - ts_pos[1]._value
 | 
						|
        result = dtimax - ts_pos
 | 
						|
        assert result[1]._value == expected
 | 
						|
 | 
						|
        expected = Timestamp.min._value - ts_neg[1]._value
 | 
						|
        result = dtimin - ts_neg
 | 
						|
        assert result[1]._value == expected
 | 
						|
        msg = "Overflow in int64 addition"
 | 
						|
        with pytest.raises(OverflowError, match=msg):
 | 
						|
            dtimax - ts_neg
 | 
						|
 | 
						|
        with pytest.raises(OverflowError, match=msg):
 | 
						|
            dtimin - ts_pos
 | 
						|
 | 
						|
        # Edge cases
 | 
						|
        tmin = pd.to_datetime([Timestamp.min])
 | 
						|
        t1 = tmin + Timedelta.max + Timedelta("1us")
 | 
						|
        with pytest.raises(OverflowError, match=msg):
 | 
						|
            t1 - tmin
 | 
						|
 | 
						|
        tmax = pd.to_datetime([Timestamp.max])
 | 
						|
        t2 = tmax + Timedelta.min - Timedelta("1us")
 | 
						|
        with pytest.raises(OverflowError, match=msg):
 | 
						|
            tmax - t2
 | 
						|
 | 
						|
 | 
						|
class TestTimestampSeriesArithmetic:
 | 
						|
    def test_empty_series_add_sub(self, box_with_array):
 | 
						|
        # GH#13844
 | 
						|
        a = Series(dtype="M8[ns]")
 | 
						|
        b = Series(dtype="m8[ns]")
 | 
						|
        a = box_with_array(a)
 | 
						|
        b = box_with_array(b)
 | 
						|
        tm.assert_equal(a, a + b)
 | 
						|
        tm.assert_equal(a, a - b)
 | 
						|
        tm.assert_equal(a, b + a)
 | 
						|
        msg = "cannot subtract"
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            b - a
 | 
						|
 | 
						|
    def test_operators_datetimelike(self):
 | 
						|
        # ## timedelta64 ###
 | 
						|
        td1 = Series([timedelta(minutes=5, seconds=3)] * 3)
 | 
						|
        td1.iloc[2] = np.nan
 | 
						|
 | 
						|
        # ## datetime64 ###
 | 
						|
        dt1 = Series(
 | 
						|
            [
 | 
						|
                Timestamp("20111230"),
 | 
						|
                Timestamp("20120101"),
 | 
						|
                Timestamp("20120103"),
 | 
						|
            ]
 | 
						|
        )
 | 
						|
        dt1.iloc[2] = np.nan
 | 
						|
        dt2 = Series(
 | 
						|
            [
 | 
						|
                Timestamp("20111231"),
 | 
						|
                Timestamp("20120102"),
 | 
						|
                Timestamp("20120104"),
 | 
						|
            ]
 | 
						|
        )
 | 
						|
        dt1 - dt2
 | 
						|
        dt2 - dt1
 | 
						|
 | 
						|
        # datetime64 with timetimedelta
 | 
						|
        dt1 + td1
 | 
						|
        td1 + dt1
 | 
						|
        dt1 - td1
 | 
						|
 | 
						|
        # timetimedelta with datetime64
 | 
						|
        td1 + dt1
 | 
						|
        dt1 + td1
 | 
						|
 | 
						|
    def test_dt64ser_sub_datetime_dtype(self, unit):
 | 
						|
        ts = Timestamp(datetime(1993, 1, 7, 13, 30, 00))
 | 
						|
        dt = datetime(1993, 6, 22, 13, 30)
 | 
						|
        ser = Series([ts], dtype=f"M8[{unit}]")
 | 
						|
        result = ser - dt
 | 
						|
 | 
						|
        # the expected unit is the max of `unit` and the unit imputed to `dt`,
 | 
						|
        #  which is "us"
 | 
						|
        exp_unit = tm.get_finest_unit(unit, "us")
 | 
						|
        assert result.dtype == f"timedelta64[{exp_unit}]"
 | 
						|
 | 
						|
    # -------------------------------------------------------------
 | 
						|
    # TODO: This next block of tests came from tests.series.test_operators,
 | 
						|
    # needs to be de-duplicated and parametrized over `box` classes
 | 
						|
 | 
						|
    @pytest.mark.parametrize(
 | 
						|
        "left, right, op_fail",
 | 
						|
        [
 | 
						|
            [
 | 
						|
                [Timestamp("20111230"), Timestamp("20120101"), NaT],
 | 
						|
                [Timestamp("20111231"), Timestamp("20120102"), Timestamp("20120104")],
 | 
						|
                ["__sub__", "__rsub__"],
 | 
						|
            ],
 | 
						|
            [
 | 
						|
                [Timestamp("20111230"), Timestamp("20120101"), NaT],
 | 
						|
                [timedelta(minutes=5, seconds=3), timedelta(minutes=5, seconds=3), NaT],
 | 
						|
                ["__add__", "__radd__", "__sub__"],
 | 
						|
            ],
 | 
						|
            [
 | 
						|
                [
 | 
						|
                    Timestamp("20111230", tz="US/Eastern"),
 | 
						|
                    Timestamp("20111230", tz="US/Eastern"),
 | 
						|
                    NaT,
 | 
						|
                ],
 | 
						|
                [timedelta(minutes=5, seconds=3), NaT, timedelta(minutes=5, seconds=3)],
 | 
						|
                ["__add__", "__radd__", "__sub__"],
 | 
						|
            ],
 | 
						|
        ],
 | 
						|
    )
 | 
						|
    def test_operators_datetimelike_invalid(
 | 
						|
        self, left, right, op_fail, all_arithmetic_operators
 | 
						|
    ):
 | 
						|
        # these are all TypeError ops
 | 
						|
        op_str = all_arithmetic_operators
 | 
						|
        arg1 = Series(left)
 | 
						|
        arg2 = Series(right)
 | 
						|
        # check that we are getting a TypeError
 | 
						|
        # with 'operate' (from core/ops.py) for the ops that are not
 | 
						|
        # defined
 | 
						|
        op = getattr(arg1, op_str, None)
 | 
						|
        # Previously, _validate_for_numeric_binop in core/indexes/base.py
 | 
						|
        # did this for us.
 | 
						|
        if op_str not in op_fail:
 | 
						|
            with pytest.raises(
 | 
						|
                TypeError, match="operate|[cC]annot|unsupported operand"
 | 
						|
            ):
 | 
						|
                op(arg2)
 | 
						|
        else:
 | 
						|
            # Smoke test
 | 
						|
            op(arg2)
 | 
						|
 | 
						|
    def test_sub_single_tz(self, unit):
 | 
						|
        # GH#12290
 | 
						|
        s1 = Series([Timestamp("2016-02-10", tz="America/Sao_Paulo")]).dt.as_unit(unit)
 | 
						|
        s2 = Series([Timestamp("2016-02-08", tz="America/Sao_Paulo")]).dt.as_unit(unit)
 | 
						|
        result = s1 - s2
 | 
						|
        expected = Series([Timedelta("2days")]).dt.as_unit(unit)
 | 
						|
        tm.assert_series_equal(result, expected)
 | 
						|
        result = s2 - s1
 | 
						|
        expected = Series([Timedelta("-2days")]).dt.as_unit(unit)
 | 
						|
        tm.assert_series_equal(result, expected)
 | 
						|
 | 
						|
    def test_dt64tz_series_sub_dtitz(self):
 | 
						|
        # GH#19071 subtracting tzaware DatetimeIndex from tzaware Series
 | 
						|
        # (with same tz) raises, fixed by #19024
 | 
						|
        dti = date_range("1999-09-30", periods=10, tz="US/Pacific")
 | 
						|
        ser = Series(dti)
 | 
						|
        expected = Series(TimedeltaIndex(["0days"] * 10))
 | 
						|
 | 
						|
        res = dti - ser
 | 
						|
        tm.assert_series_equal(res, expected)
 | 
						|
        res = ser - dti
 | 
						|
        tm.assert_series_equal(res, expected)
 | 
						|
 | 
						|
    def test_sub_datetime_compat(self, unit):
 | 
						|
        # see GH#14088
 | 
						|
        ser = Series([datetime(2016, 8, 23, 12, tzinfo=pytz.utc), NaT]).dt.as_unit(unit)
 | 
						|
        dt = datetime(2016, 8, 22, 12, tzinfo=pytz.utc)
 | 
						|
        # The datetime object has "us" so we upcast lower units
 | 
						|
        exp_unit = tm.get_finest_unit(unit, "us")
 | 
						|
        exp = Series([Timedelta("1 days"), NaT]).dt.as_unit(exp_unit)
 | 
						|
        result = ser - dt
 | 
						|
        tm.assert_series_equal(result, exp)
 | 
						|
        result2 = ser - Timestamp(dt)
 | 
						|
        tm.assert_series_equal(result2, exp)
 | 
						|
 | 
						|
    def test_dt64_series_add_mixed_tick_DateOffset(self):
 | 
						|
        # GH#4532
 | 
						|
        # operate with pd.offsets
 | 
						|
        s = Series([Timestamp("20130101 9:01"), Timestamp("20130101 9:02")])
 | 
						|
 | 
						|
        result = s + pd.offsets.Milli(5)
 | 
						|
        result2 = pd.offsets.Milli(5) + s
 | 
						|
        expected = Series(
 | 
						|
            [Timestamp("20130101 9:01:00.005"), Timestamp("20130101 9:02:00.005")]
 | 
						|
        )
 | 
						|
        tm.assert_series_equal(result, expected)
 | 
						|
        tm.assert_series_equal(result2, expected)
 | 
						|
 | 
						|
        result = s + pd.offsets.Minute(5) + pd.offsets.Milli(5)
 | 
						|
        expected = Series(
 | 
						|
            [Timestamp("20130101 9:06:00.005"), Timestamp("20130101 9:07:00.005")]
 | 
						|
        )
 | 
						|
        tm.assert_series_equal(result, expected)
 | 
						|
 | 
						|
    def test_datetime64_ops_nat(self, unit):
 | 
						|
        # GH#11349
 | 
						|
        datetime_series = Series([NaT, Timestamp("19900315")]).dt.as_unit(unit)
 | 
						|
        nat_series_dtype_timestamp = Series([NaT, NaT], dtype=f"datetime64[{unit}]")
 | 
						|
        single_nat_dtype_datetime = Series([NaT], dtype=f"datetime64[{unit}]")
 | 
						|
 | 
						|
        # subtraction
 | 
						|
        tm.assert_series_equal(-NaT + datetime_series, nat_series_dtype_timestamp)
 | 
						|
        msg = "bad operand type for unary -: 'DatetimeArray'"
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            -single_nat_dtype_datetime + datetime_series
 | 
						|
 | 
						|
        tm.assert_series_equal(
 | 
						|
            -NaT + nat_series_dtype_timestamp, nat_series_dtype_timestamp
 | 
						|
        )
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            -single_nat_dtype_datetime + nat_series_dtype_timestamp
 | 
						|
 | 
						|
        # addition
 | 
						|
        tm.assert_series_equal(
 | 
						|
            nat_series_dtype_timestamp + NaT, nat_series_dtype_timestamp
 | 
						|
        )
 | 
						|
        tm.assert_series_equal(
 | 
						|
            NaT + nat_series_dtype_timestamp, nat_series_dtype_timestamp
 | 
						|
        )
 | 
						|
 | 
						|
        tm.assert_series_equal(
 | 
						|
            nat_series_dtype_timestamp + NaT, nat_series_dtype_timestamp
 | 
						|
        )
 | 
						|
        tm.assert_series_equal(
 | 
						|
            NaT + nat_series_dtype_timestamp, nat_series_dtype_timestamp
 | 
						|
        )
 | 
						|
 | 
						|
    # -------------------------------------------------------------
 | 
						|
    # Timezone-Centric Tests
 | 
						|
 | 
						|
    def test_operators_datetimelike_with_timezones(self):
 | 
						|
        tz = "US/Eastern"
 | 
						|
        dt1 = Series(date_range("2000-01-01 09:00:00", periods=5, tz=tz), name="foo")
 | 
						|
        dt2 = dt1.copy()
 | 
						|
        dt2.iloc[2] = np.nan
 | 
						|
 | 
						|
        td1 = Series(pd.timedelta_range("1 days 1 min", periods=5, freq="h"))
 | 
						|
        td2 = td1.copy()
 | 
						|
        td2.iloc[1] = np.nan
 | 
						|
        assert td2._values.freq is None
 | 
						|
 | 
						|
        result = dt1 + td1[0]
 | 
						|
        exp = (dt1.dt.tz_localize(None) + td1[0]).dt.tz_localize(tz)
 | 
						|
        tm.assert_series_equal(result, exp)
 | 
						|
 | 
						|
        result = dt2 + td2[0]
 | 
						|
        exp = (dt2.dt.tz_localize(None) + td2[0]).dt.tz_localize(tz)
 | 
						|
        tm.assert_series_equal(result, exp)
 | 
						|
 | 
						|
        # odd numpy behavior with scalar timedeltas
 | 
						|
        result = td1[0] + dt1
 | 
						|
        exp = (dt1.dt.tz_localize(None) + td1[0]).dt.tz_localize(tz)
 | 
						|
        tm.assert_series_equal(result, exp)
 | 
						|
 | 
						|
        result = td2[0] + dt2
 | 
						|
        exp = (dt2.dt.tz_localize(None) + td2[0]).dt.tz_localize(tz)
 | 
						|
        tm.assert_series_equal(result, exp)
 | 
						|
 | 
						|
        result = dt1 - td1[0]
 | 
						|
        exp = (dt1.dt.tz_localize(None) - td1[0]).dt.tz_localize(tz)
 | 
						|
        tm.assert_series_equal(result, exp)
 | 
						|
        msg = "(bad|unsupported) operand type for unary"
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            td1[0] - dt1
 | 
						|
 | 
						|
        result = dt2 - td2[0]
 | 
						|
        exp = (dt2.dt.tz_localize(None) - td2[0]).dt.tz_localize(tz)
 | 
						|
        tm.assert_series_equal(result, exp)
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            td2[0] - dt2
 | 
						|
 | 
						|
        result = dt1 + td1
 | 
						|
        exp = (dt1.dt.tz_localize(None) + td1).dt.tz_localize(tz)
 | 
						|
        tm.assert_series_equal(result, exp)
 | 
						|
 | 
						|
        result = dt2 + td2
 | 
						|
        exp = (dt2.dt.tz_localize(None) + td2).dt.tz_localize(tz)
 | 
						|
        tm.assert_series_equal(result, exp)
 | 
						|
 | 
						|
        result = dt1 - td1
 | 
						|
        exp = (dt1.dt.tz_localize(None) - td1).dt.tz_localize(tz)
 | 
						|
        tm.assert_series_equal(result, exp)
 | 
						|
 | 
						|
        result = dt2 - td2
 | 
						|
        exp = (dt2.dt.tz_localize(None) - td2).dt.tz_localize(tz)
 | 
						|
        tm.assert_series_equal(result, exp)
 | 
						|
        msg = "cannot (add|subtract)"
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            td1 - dt1
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            td2 - dt2
 | 
						|
 | 
						|
 | 
						|
class TestDatetimeIndexArithmetic:
 | 
						|
    # -------------------------------------------------------------
 | 
						|
    # Binary operations DatetimeIndex and TimedeltaIndex/array
 | 
						|
 | 
						|
    def test_dti_add_tdi(self, tz_naive_fixture):
 | 
						|
        # GH#17558
 | 
						|
        tz = tz_naive_fixture
 | 
						|
        dti = DatetimeIndex([Timestamp("2017-01-01", tz=tz)] * 10)
 | 
						|
        tdi = pd.timedelta_range("0 days", periods=10)
 | 
						|
        expected = date_range("2017-01-01", periods=10, tz=tz)
 | 
						|
        expected = expected._with_freq(None)
 | 
						|
 | 
						|
        # add with TimedeltaIndex
 | 
						|
        result = dti + tdi
 | 
						|
        tm.assert_index_equal(result, expected)
 | 
						|
 | 
						|
        result = tdi + dti
 | 
						|
        tm.assert_index_equal(result, expected)
 | 
						|
 | 
						|
        # add with timedelta64 array
 | 
						|
        result = dti + tdi.values
 | 
						|
        tm.assert_index_equal(result, expected)
 | 
						|
 | 
						|
        result = tdi.values + dti
 | 
						|
        tm.assert_index_equal(result, expected)
 | 
						|
 | 
						|
    def test_dti_iadd_tdi(self, tz_naive_fixture):
 | 
						|
        # GH#17558
 | 
						|
        tz = tz_naive_fixture
 | 
						|
        dti = DatetimeIndex([Timestamp("2017-01-01", tz=tz)] * 10)
 | 
						|
        tdi = pd.timedelta_range("0 days", periods=10)
 | 
						|
        expected = date_range("2017-01-01", periods=10, tz=tz)
 | 
						|
        expected = expected._with_freq(None)
 | 
						|
 | 
						|
        # iadd with TimedeltaIndex
 | 
						|
        result = DatetimeIndex([Timestamp("2017-01-01", tz=tz)] * 10)
 | 
						|
        result += tdi
 | 
						|
        tm.assert_index_equal(result, expected)
 | 
						|
 | 
						|
        result = pd.timedelta_range("0 days", periods=10)
 | 
						|
        result += dti
 | 
						|
        tm.assert_index_equal(result, expected)
 | 
						|
 | 
						|
        # iadd with timedelta64 array
 | 
						|
        result = DatetimeIndex([Timestamp("2017-01-01", tz=tz)] * 10)
 | 
						|
        result += tdi.values
 | 
						|
        tm.assert_index_equal(result, expected)
 | 
						|
 | 
						|
        result = pd.timedelta_range("0 days", periods=10)
 | 
						|
        result += dti
 | 
						|
        tm.assert_index_equal(result, expected)
 | 
						|
 | 
						|
    def test_dti_sub_tdi(self, tz_naive_fixture):
 | 
						|
        # GH#17558
 | 
						|
        tz = tz_naive_fixture
 | 
						|
        dti = DatetimeIndex([Timestamp("2017-01-01", tz=tz)] * 10)
 | 
						|
        tdi = pd.timedelta_range("0 days", periods=10)
 | 
						|
        expected = date_range("2017-01-01", periods=10, tz=tz, freq="-1D")
 | 
						|
        expected = expected._with_freq(None)
 | 
						|
 | 
						|
        # sub with TimedeltaIndex
 | 
						|
        result = dti - tdi
 | 
						|
        tm.assert_index_equal(result, expected)
 | 
						|
 | 
						|
        msg = "cannot subtract .*TimedeltaArray"
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            tdi - dti
 | 
						|
 | 
						|
        # sub with timedelta64 array
 | 
						|
        result = dti - tdi.values
 | 
						|
        tm.assert_index_equal(result, expected)
 | 
						|
 | 
						|
        msg = "cannot subtract a datelike from a TimedeltaArray"
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            tdi.values - dti
 | 
						|
 | 
						|
    def test_dti_isub_tdi(self, tz_naive_fixture, unit):
 | 
						|
        # GH#17558
 | 
						|
        tz = tz_naive_fixture
 | 
						|
        dti = DatetimeIndex([Timestamp("2017-01-01", tz=tz)] * 10).as_unit(unit)
 | 
						|
        tdi = pd.timedelta_range("0 days", periods=10, unit=unit)
 | 
						|
        expected = date_range("2017-01-01", periods=10, tz=tz, freq="-1D", unit=unit)
 | 
						|
        expected = expected._with_freq(None)
 | 
						|
 | 
						|
        # isub with TimedeltaIndex
 | 
						|
        result = DatetimeIndex([Timestamp("2017-01-01", tz=tz)] * 10).as_unit(unit)
 | 
						|
        result -= tdi
 | 
						|
        tm.assert_index_equal(result, expected)
 | 
						|
 | 
						|
        # DTA.__isub__ GH#43904
 | 
						|
        dta = dti._data.copy()
 | 
						|
        dta -= tdi
 | 
						|
        tm.assert_datetime_array_equal(dta, expected._data)
 | 
						|
 | 
						|
        out = dti._data.copy()
 | 
						|
        np.subtract(out, tdi, out=out)
 | 
						|
        tm.assert_datetime_array_equal(out, expected._data)
 | 
						|
 | 
						|
        msg = "cannot subtract a datelike from a TimedeltaArray"
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            tdi -= dti
 | 
						|
 | 
						|
        # isub with timedelta64 array
 | 
						|
        result = DatetimeIndex([Timestamp("2017-01-01", tz=tz)] * 10).as_unit(unit)
 | 
						|
        result -= tdi.values
 | 
						|
        tm.assert_index_equal(result, expected)
 | 
						|
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            tdi.values -= dti
 | 
						|
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            tdi._values -= dti
 | 
						|
 | 
						|
    # -------------------------------------------------------------
 | 
						|
    # Binary Operations DatetimeIndex and datetime-like
 | 
						|
    # TODO: A couple other tests belong in this section.  Move them in
 | 
						|
    # A PR where there isn't already a giant diff.
 | 
						|
 | 
						|
    # -------------------------------------------------------------
 | 
						|
 | 
						|
    def test_dta_add_sub_index(self, tz_naive_fixture):
 | 
						|
        # Check that DatetimeArray defers to Index classes
 | 
						|
        dti = date_range("20130101", periods=3, tz=tz_naive_fixture)
 | 
						|
        dta = dti.array
 | 
						|
        result = dta - dti
 | 
						|
        expected = dti - dti
 | 
						|
        tm.assert_index_equal(result, expected)
 | 
						|
 | 
						|
        tdi = result
 | 
						|
        result = dta + tdi
 | 
						|
        expected = dti + tdi
 | 
						|
        tm.assert_index_equal(result, expected)
 | 
						|
 | 
						|
        result = dta - tdi
 | 
						|
        expected = dti - tdi
 | 
						|
        tm.assert_index_equal(result, expected)
 | 
						|
 | 
						|
    def test_sub_dti_dti(self, unit):
 | 
						|
        # previously performed setop (deprecated in 0.16.0), now changed to
 | 
						|
        # return subtraction -> TimeDeltaIndex (GH ...)
 | 
						|
 | 
						|
        dti = date_range("20130101", periods=3, unit=unit)
 | 
						|
        dti_tz = date_range("20130101", periods=3, unit=unit).tz_localize("US/Eastern")
 | 
						|
        expected = TimedeltaIndex([0, 0, 0]).as_unit(unit)
 | 
						|
 | 
						|
        result = dti - dti
 | 
						|
        tm.assert_index_equal(result, expected)
 | 
						|
 | 
						|
        result = dti_tz - dti_tz
 | 
						|
        tm.assert_index_equal(result, expected)
 | 
						|
        msg = "Cannot subtract tz-naive and tz-aware datetime-like objects"
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            dti_tz - dti
 | 
						|
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            dti - dti_tz
 | 
						|
 | 
						|
        # isub
 | 
						|
        dti -= dti
 | 
						|
        tm.assert_index_equal(dti, expected)
 | 
						|
 | 
						|
        # different length raises ValueError
 | 
						|
        dti1 = date_range("20130101", periods=3, unit=unit)
 | 
						|
        dti2 = date_range("20130101", periods=4, unit=unit)
 | 
						|
        msg = "cannot add indices of unequal length"
 | 
						|
        with pytest.raises(ValueError, match=msg):
 | 
						|
            dti1 - dti2
 | 
						|
 | 
						|
        # NaN propagation
 | 
						|
        dti1 = DatetimeIndex(["2012-01-01", np.nan, "2012-01-03"]).as_unit(unit)
 | 
						|
        dti2 = DatetimeIndex(["2012-01-02", "2012-01-03", np.nan]).as_unit(unit)
 | 
						|
        expected = TimedeltaIndex(["1 days", np.nan, np.nan]).as_unit(unit)
 | 
						|
        result = dti2 - dti1
 | 
						|
        tm.assert_index_equal(result, expected)
 | 
						|
 | 
						|
    # -------------------------------------------------------------------
 | 
						|
    # TODO: Most of this block is moved from series or frame tests, needs
 | 
						|
    # cleanup, box-parametrization, and de-duplication
 | 
						|
 | 
						|
    @pytest.mark.parametrize("op", [operator.add, operator.sub])
 | 
						|
    def test_timedelta64_equal_timedelta_supported_ops(self, op, box_with_array):
 | 
						|
        ser = Series(
 | 
						|
            [
 | 
						|
                Timestamp("20130301"),
 | 
						|
                Timestamp("20130228 23:00:00"),
 | 
						|
                Timestamp("20130228 22:00:00"),
 | 
						|
                Timestamp("20130228 21:00:00"),
 | 
						|
            ]
 | 
						|
        )
 | 
						|
        obj = box_with_array(ser)
 | 
						|
 | 
						|
        intervals = ["D", "h", "m", "s", "us"]
 | 
						|
 | 
						|
        def timedelta64(*args):
 | 
						|
            # see casting notes in NumPy gh-12927
 | 
						|
            return np.sum(list(starmap(np.timedelta64, zip(args, intervals))))
 | 
						|
 | 
						|
        for d, h, m, s, us in product(*([range(2)] * 5)):
 | 
						|
            nptd = timedelta64(d, h, m, s, us)
 | 
						|
            pytd = timedelta(days=d, hours=h, minutes=m, seconds=s, microseconds=us)
 | 
						|
            lhs = op(obj, nptd)
 | 
						|
            rhs = op(obj, pytd)
 | 
						|
 | 
						|
            tm.assert_equal(lhs, rhs)
 | 
						|
 | 
						|
    def test_ops_nat_mixed_datetime64_timedelta64(self):
 | 
						|
        # GH#11349
 | 
						|
        timedelta_series = Series([NaT, Timedelta("1s")])
 | 
						|
        datetime_series = Series([NaT, Timestamp("19900315")])
 | 
						|
        nat_series_dtype_timedelta = Series([NaT, NaT], dtype="timedelta64[ns]")
 | 
						|
        nat_series_dtype_timestamp = Series([NaT, NaT], dtype="datetime64[ns]")
 | 
						|
        single_nat_dtype_datetime = Series([NaT], dtype="datetime64[ns]")
 | 
						|
        single_nat_dtype_timedelta = Series([NaT], dtype="timedelta64[ns]")
 | 
						|
 | 
						|
        # subtraction
 | 
						|
        tm.assert_series_equal(
 | 
						|
            datetime_series - single_nat_dtype_datetime, nat_series_dtype_timedelta
 | 
						|
        )
 | 
						|
 | 
						|
        tm.assert_series_equal(
 | 
						|
            datetime_series - single_nat_dtype_timedelta, nat_series_dtype_timestamp
 | 
						|
        )
 | 
						|
        tm.assert_series_equal(
 | 
						|
            -single_nat_dtype_timedelta + datetime_series, nat_series_dtype_timestamp
 | 
						|
        )
 | 
						|
 | 
						|
        # without a Series wrapping the NaT, it is ambiguous
 | 
						|
        # whether it is a datetime64 or timedelta64
 | 
						|
        # defaults to interpreting it as timedelta64
 | 
						|
        tm.assert_series_equal(
 | 
						|
            nat_series_dtype_timestamp - single_nat_dtype_datetime,
 | 
						|
            nat_series_dtype_timedelta,
 | 
						|
        )
 | 
						|
 | 
						|
        tm.assert_series_equal(
 | 
						|
            nat_series_dtype_timestamp - single_nat_dtype_timedelta,
 | 
						|
            nat_series_dtype_timestamp,
 | 
						|
        )
 | 
						|
        tm.assert_series_equal(
 | 
						|
            -single_nat_dtype_timedelta + nat_series_dtype_timestamp,
 | 
						|
            nat_series_dtype_timestamp,
 | 
						|
        )
 | 
						|
        msg = "cannot subtract a datelike"
 | 
						|
        with pytest.raises(TypeError, match=msg):
 | 
						|
            timedelta_series - single_nat_dtype_datetime
 | 
						|
 | 
						|
        # addition
 | 
						|
        tm.assert_series_equal(
 | 
						|
            nat_series_dtype_timestamp + single_nat_dtype_timedelta,
 | 
						|
            nat_series_dtype_timestamp,
 | 
						|
        )
 | 
						|
        tm.assert_series_equal(
 | 
						|
            single_nat_dtype_timedelta + nat_series_dtype_timestamp,
 | 
						|
            nat_series_dtype_timestamp,
 | 
						|
        )
 | 
						|
 | 
						|
        tm.assert_series_equal(
 | 
						|
            nat_series_dtype_timestamp + single_nat_dtype_timedelta,
 | 
						|
            nat_series_dtype_timestamp,
 | 
						|
        )
 | 
						|
        tm.assert_series_equal(
 | 
						|
            single_nat_dtype_timedelta + nat_series_dtype_timestamp,
 | 
						|
            nat_series_dtype_timestamp,
 | 
						|
        )
 | 
						|
 | 
						|
        tm.assert_series_equal(
 | 
						|
            nat_series_dtype_timedelta + single_nat_dtype_datetime,
 | 
						|
            nat_series_dtype_timestamp,
 | 
						|
        )
 | 
						|
        tm.assert_series_equal(
 | 
						|
            single_nat_dtype_datetime + nat_series_dtype_timedelta,
 | 
						|
            nat_series_dtype_timestamp,
 | 
						|
        )
 | 
						|
 | 
						|
    def test_ufunc_coercions(self, unit):
 | 
						|
        idx = date_range("2011-01-01", periods=3, freq="2D", name="x", unit=unit)
 | 
						|
 | 
						|
        delta = np.timedelta64(1, "D")
 | 
						|
        exp = date_range("2011-01-02", periods=3, freq="2D", name="x", unit=unit)
 | 
						|
        for result in [idx + delta, np.add(idx, delta)]:
 | 
						|
            assert isinstance(result, DatetimeIndex)
 | 
						|
            tm.assert_index_equal(result, exp)
 | 
						|
            assert result.freq == "2D"
 | 
						|
 | 
						|
        exp = date_range("2010-12-31", periods=3, freq="2D", name="x", unit=unit)
 | 
						|
 | 
						|
        for result in [idx - delta, np.subtract(idx, delta)]:
 | 
						|
            assert isinstance(result, DatetimeIndex)
 | 
						|
            tm.assert_index_equal(result, exp)
 | 
						|
            assert result.freq == "2D"
 | 
						|
 | 
						|
        # When adding/subtracting an ndarray (which has no .freq), the result
 | 
						|
        #  does not infer freq
 | 
						|
        idx = idx._with_freq(None)
 | 
						|
        delta = np.array(
 | 
						|
            [np.timedelta64(1, "D"), np.timedelta64(2, "D"), np.timedelta64(3, "D")]
 | 
						|
        )
 | 
						|
        exp = DatetimeIndex(
 | 
						|
            ["2011-01-02", "2011-01-05", "2011-01-08"], name="x"
 | 
						|
        ).as_unit(unit)
 | 
						|
 | 
						|
        for result in [idx + delta, np.add(idx, delta)]:
 | 
						|
            tm.assert_index_equal(result, exp)
 | 
						|
            assert result.freq == exp.freq
 | 
						|
 | 
						|
        exp = DatetimeIndex(
 | 
						|
            ["2010-12-31", "2011-01-01", "2011-01-02"], name="x"
 | 
						|
        ).as_unit(unit)
 | 
						|
        for result in [idx - delta, np.subtract(idx, delta)]:
 | 
						|
            assert isinstance(result, DatetimeIndex)
 | 
						|
            tm.assert_index_equal(result, exp)
 | 
						|
            assert result.freq == exp.freq
 | 
						|
 | 
						|
    def test_dti_add_series(self, tz_naive_fixture, names):
 | 
						|
        # GH#13905
 | 
						|
        tz = tz_naive_fixture
 | 
						|
        index = DatetimeIndex(
 | 
						|
            ["2016-06-28 05:30", "2016-06-28 05:31"], tz=tz, name=names[0]
 | 
						|
        ).as_unit("ns")
 | 
						|
        ser = Series([Timedelta(seconds=5)] * 2, index=index, name=names[1])
 | 
						|
        expected = Series(index + Timedelta(seconds=5), index=index, name=names[2])
 | 
						|
 | 
						|
        # passing name arg isn't enough when names[2] is None
 | 
						|
        expected.name = names[2]
 | 
						|
        assert expected.dtype == index.dtype
 | 
						|
        result = ser + index
 | 
						|
        tm.assert_series_equal(result, expected)
 | 
						|
        result2 = index + ser
 | 
						|
        tm.assert_series_equal(result2, expected)
 | 
						|
 | 
						|
        expected = index + Timedelta(seconds=5)
 | 
						|
        result3 = ser.values + index
 | 
						|
        tm.assert_index_equal(result3, expected)
 | 
						|
        result4 = index + ser.values
 | 
						|
        tm.assert_index_equal(result4, expected)
 | 
						|
 | 
						|
    @pytest.mark.parametrize("op", [operator.add, roperator.radd, operator.sub])
 | 
						|
    def test_dti_addsub_offset_arraylike(
 | 
						|
        self, tz_naive_fixture, names, op, index_or_series
 | 
						|
    ):
 | 
						|
        # GH#18849, GH#19744
 | 
						|
        other_box = index_or_series
 | 
						|
 | 
						|
        tz = tz_naive_fixture
 | 
						|
        dti = date_range("2017-01-01", periods=2, tz=tz, name=names[0])
 | 
						|
        other = other_box([pd.offsets.MonthEnd(), pd.offsets.Day(n=2)], name=names[1])
 | 
						|
 | 
						|
        xbox = get_upcast_box(dti, other)
 | 
						|
 | 
						|
        with tm.assert_produces_warning(PerformanceWarning):
 | 
						|
            res = op(dti, other)
 | 
						|
 | 
						|
        expected = DatetimeIndex(
 | 
						|
            [op(dti[n], other[n]) for n in range(len(dti))], name=names[2], freq="infer"
 | 
						|
        )
 | 
						|
        expected = tm.box_expected(expected, xbox).astype(object)
 | 
						|
        tm.assert_equal(res, expected)
 | 
						|
 | 
						|
    @pytest.mark.parametrize("other_box", [pd.Index, np.array])
 | 
						|
    def test_dti_addsub_object_arraylike(
 | 
						|
        self, tz_naive_fixture, box_with_array, other_box
 | 
						|
    ):
 | 
						|
        tz = tz_naive_fixture
 | 
						|
 | 
						|
        dti = date_range("2017-01-01", periods=2, tz=tz)
 | 
						|
        dtarr = tm.box_expected(dti, box_with_array)
 | 
						|
        other = other_box([pd.offsets.MonthEnd(), Timedelta(days=4)])
 | 
						|
        xbox = get_upcast_box(dtarr, other)
 | 
						|
 | 
						|
        expected = DatetimeIndex(["2017-01-31", "2017-01-06"], tz=tz_naive_fixture)
 | 
						|
        expected = tm.box_expected(expected, xbox).astype(object)
 | 
						|
 | 
						|
        with tm.assert_produces_warning(PerformanceWarning):
 | 
						|
            result = dtarr + other
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
 | 
						|
        expected = DatetimeIndex(["2016-12-31", "2016-12-29"], tz=tz_naive_fixture)
 | 
						|
        expected = tm.box_expected(expected, xbox).astype(object)
 | 
						|
 | 
						|
        with tm.assert_produces_warning(PerformanceWarning):
 | 
						|
            result = dtarr - other
 | 
						|
        tm.assert_equal(result, expected)
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.parametrize("years", [-1, 0, 1])
 | 
						|
@pytest.mark.parametrize("months", [-2, 0, 2])
 | 
						|
@pytest.mark.parametrize("unit", ["s", "ms", "us", "ns"])
 | 
						|
def test_shift_months(years, months, unit):
 | 
						|
    dti = DatetimeIndex(
 | 
						|
        [
 | 
						|
            Timestamp("2000-01-05 00:15:00"),
 | 
						|
            Timestamp("2000-01-31 00:23:00"),
 | 
						|
            Timestamp("2000-01-01"),
 | 
						|
            Timestamp("2000-02-29"),
 | 
						|
            Timestamp("2000-12-31"),
 | 
						|
        ]
 | 
						|
    ).as_unit(unit)
 | 
						|
    shifted = shift_months(dti.asi8, years * 12 + months, reso=dti._data._creso)
 | 
						|
    shifted_dt64 = shifted.view(f"M8[{dti.unit}]")
 | 
						|
    actual = DatetimeIndex(shifted_dt64)
 | 
						|
 | 
						|
    raw = [x + pd.offsets.DateOffset(years=years, months=months) for x in dti]
 | 
						|
    expected = DatetimeIndex(raw).as_unit(dti.unit)
 | 
						|
    tm.assert_index_equal(actual, expected)
 | 
						|
 | 
						|
 | 
						|
def test_dt64arr_addsub_object_dtype_2d():
 | 
						|
    # block-wise DataFrame operations will require operating on 2D
 | 
						|
    #  DatetimeArray/TimedeltaArray, so check that specifically.
 | 
						|
    dti = date_range("1994-02-13", freq="2W", periods=4)
 | 
						|
    dta = dti._data.reshape((4, 1))
 | 
						|
 | 
						|
    other = np.array([[pd.offsets.Day(n)] for n in range(4)])
 | 
						|
    assert other.shape == dta.shape
 | 
						|
 | 
						|
    with tm.assert_produces_warning(PerformanceWarning):
 | 
						|
        result = dta + other
 | 
						|
    with tm.assert_produces_warning(PerformanceWarning):
 | 
						|
        expected = (dta[:, 0] + other[:, 0]).reshape(-1, 1)
 | 
						|
 | 
						|
    tm.assert_numpy_array_equal(result, expected)
 | 
						|
 | 
						|
    with tm.assert_produces_warning(PerformanceWarning):
 | 
						|
        # Case where we expect to get a TimedeltaArray back
 | 
						|
        result2 = dta - dta.astype(object)
 | 
						|
 | 
						|
    assert result2.shape == (4, 1)
 | 
						|
    assert all(td._value == 0 for td in result2.ravel())
 | 
						|
 | 
						|
 | 
						|
def test_non_nano_dt64_addsub_np_nat_scalars():
 | 
						|
    # GH 52295
 | 
						|
    ser = Series([1233242342344, 232432434324, 332434242344], dtype="datetime64[ms]")
 | 
						|
    result = ser - np.datetime64("nat", "ms")
 | 
						|
    expected = Series([NaT] * 3, dtype="timedelta64[ms]")
 | 
						|
    tm.assert_series_equal(result, expected)
 | 
						|
 | 
						|
    result = ser + np.timedelta64("nat", "ms")
 | 
						|
    expected = Series([NaT] * 3, dtype="datetime64[ms]")
 | 
						|
    tm.assert_series_equal(result, expected)
 | 
						|
 | 
						|
 | 
						|
def test_non_nano_dt64_addsub_np_nat_scalars_unitless():
 | 
						|
    # GH 52295
 | 
						|
    # TODO: Can we default to the ser unit?
 | 
						|
    ser = Series([1233242342344, 232432434324, 332434242344], dtype="datetime64[ms]")
 | 
						|
    result = ser - np.datetime64("nat")
 | 
						|
    expected = Series([NaT] * 3, dtype="timedelta64[ns]")
 | 
						|
    tm.assert_series_equal(result, expected)
 | 
						|
 | 
						|
    result = ser + np.timedelta64("nat")
 | 
						|
    expected = Series([NaT] * 3, dtype="datetime64[ns]")
 | 
						|
    tm.assert_series_equal(result, expected)
 | 
						|
 | 
						|
 | 
						|
def test_non_nano_dt64_addsub_np_nat_scalars_unsupported_unit():
 | 
						|
    # GH 52295
 | 
						|
    ser = Series([12332, 23243, 33243], dtype="datetime64[s]")
 | 
						|
    result = ser - np.datetime64("nat", "D")
 | 
						|
    expected = Series([NaT] * 3, dtype="timedelta64[s]")
 | 
						|
    tm.assert_series_equal(result, expected)
 | 
						|
 | 
						|
    result = ser + np.timedelta64("nat", "D")
 | 
						|
    expected = Series([NaT] * 3, dtype="datetime64[s]")
 | 
						|
    tm.assert_series_equal(result, expected)
 |