class TestTimedeltaAdditionSubtraction: """ Tests for Timedelta methods: __add__, __radd__, __sub__, __rsub__ """ @pytest.mark.parametrize( "ten_seconds", [ Timedelta(10, unit="s"), timedelta(seconds=10), np.timedelta64(10, "s"), np.timedelta64(10000000000, "ns"), offsets.Second(10), ], ) def test_td_add_sub_ten_seconds(self, ten_seconds): # GH#6808 base = Timestamp("20130101 09:01:12.123456") expected_add = Timestamp("20130101 09:01:22.123456") expected_sub = Timestamp("20130101 09:01:02.123456") result = base + ten_seconds assert result == expected_add result = base - ten_seconds assert result == expected_sub @pytest.mark.parametrize( "one_day_ten_secs", [ Timedelta("1 day, 00:00:10"), Timedelta("1 days, 00:00:10"), timedelta(days=1, seconds=10), np.timedelta64(1, "D") + np.timedelta64(10, "s"), offsets.Day() + offsets.Second(10), ], ) def test_td_add_sub_one_day_ten_seconds(self, one_day_ten_secs): # GH#6808 base = Timestamp("20130102 09:01:12.123456") expected_add = Timestamp("20130103 09:01:22.123456") expected_sub = Timestamp("20130101 09:01:02.123456") result = base + one_day_ten_secs assert result == expected_add result = base - one_day_ten_secs assert result == expected_sub @pytest.mark.parametrize("op", [operator.add, ops.radd]) def test_td_add_datetimelike_scalar(self, op): # GH#19738 td = Timedelta(10, unit="d") result = op(td, datetime(2016, 1, 1)) if op is operator.add: # datetime + Timedelta does _not_ call Timedelta.__radd__, # so we get a datetime back instead of a Timestamp assert isinstance(result, Timestamp) assert result == Timestamp(2016, 1, 11) result = op(td, Timestamp("2018-01-12 18:09")) assert isinstance(result, Timestamp) assert result == Timestamp("2018-01-22 18:09") result = op(td, np.datetime64("2018-01-12")) assert isinstance(result, Timestamp) assert result == Timestamp("2018-01-22") result = op(td, NaT) assert result is NaT def test_td_add_timestamp_overflow(self): msg = "int too (large|big) to convert" with pytest.raises(OverflowError, match=msg): Timestamp("1700-01-01") + Timedelta(13 * 19999, unit="D") with pytest.raises(OverflowError, match=msg): Timestamp("1700-01-01") + timedelta(days=13 * 19999) @pytest.mark.parametrize("op", [operator.add, ops.radd]) def test_td_add_td(self, op): td = Timedelta(10, unit="d") result = op(td, Timedelta(days=10)) assert isinstance(result, Timedelta) assert result == Timedelta(days=20) @pytest.mark.parametrize("op", [operator.add, ops.radd]) def test_td_add_pytimedelta(self, op): td = Timedelta(10, unit="d") result = op(td, timedelta(days=9)) assert isinstance(result, Timedelta) assert result == Timedelta(days=19) @pytest.mark.parametrize("op", [operator.add, ops.radd]) def test_td_add_timedelta64(self, op): td = Timedelta(10, unit="d") result = op(td, np.timedelta64(-4, "D")) assert isinstance(result, Timedelta) assert result == Timedelta(days=6) @pytest.mark.parametrize("op", [operator.add, ops.radd]) def test_td_add_offset(self, op): td = Timedelta(10, unit="d") result = op(td, offsets.Hour(6)) assert isinstance(result, Timedelta) assert result == Timedelta(days=10, hours=6) def test_td_sub_td(self): td = Timedelta(10, unit="d") expected = Timedelta(0, unit="ns") result = td - td assert isinstance(result, Timedelta) assert result == expected def test_td_sub_pytimedelta(self): td = Timedelta(10, unit="d") expected = Timedelta(0, unit="ns") result = td - td.to_pytimedelta() assert isinstance(result, Timedelta) assert result == expected result = td.to_pytimedelta() - td assert isinstance(result, Timedelta) assert result == expected def test_td_sub_timedelta64(self): td = Timedelta(10, unit="d") expected = Timedelta(0, unit="ns") result = td - td.to_timedelta64() assert isinstance(result, Timedelta) assert result == expected result = td.to_timedelta64() - td assert isinstance(result, Timedelta) assert result == expected def test_td_sub_nat(self): # In this context pd.NaT is treated as timedelta-like td = Timedelta(10, unit="d") result = td - NaT assert result is NaT def test_td_sub_td64_nat(self): td = Timedelta(10, unit="d") td_nat = np.timedelta64("NaT") result = td - td_nat assert result is NaT result = td_nat - td assert result is NaT def test_td_sub_offset(self): td = Timedelta(10, unit="d") result = td - offsets.Hour(1) assert isinstance(result, Timedelta) assert result == Timedelta(239, unit="h") def test_td_add_sub_numeric_raises(self): td = Timedelta(10, unit="d") msg = "unsupported operand type" for other in [2, 2.0, np.int64(2), np.float64(2)]: with pytest.raises(TypeError, match=msg): td + other with pytest.raises(TypeError, match=msg): other + td with pytest.raises(TypeError, match=msg): td - other with pytest.raises(TypeError, match=msg): other - td def test_td_rsub_nat(self): td = Timedelta(10, unit="d") result = NaT - td assert result is NaT result = np.datetime64("NaT") - td assert result is NaT def test_td_rsub_offset(self): result = offsets.Hour(1) - Timedelta(10, unit="d") assert isinstance(result, Timedelta) assert result == Timedelta(-239, unit="h") def test_td_sub_timedeltalike_object_dtype_array(self): # GH#21980 arr = np.array( [Timestamp("20130101 9:01"), Timestamp("20121230 9:02")]) exp = np.array( [Timestamp("20121231 9:01"), Timestamp("20121229 9:02")]) res = arr - Timedelta("1D") tm.assert_numpy_array_equal(res, exp) def test_td_sub_mixed_most_timedeltalike_object_dtype_array(self): # GH#21980 now = Timestamp.now() arr = np.array([now, Timedelta("1D"), np.timedelta64(2, "h")]) exp = np.array([ now - Timedelta("1D"), Timedelta("0D"), np.timedelta64(2, "h") - Timedelta("1D"), ]) res = arr - Timedelta("1D") tm.assert_numpy_array_equal(res, exp) def test_td_rsub_mixed_most_timedeltalike_object_dtype_array(self): # GH#21980 now = Timestamp.now() arr = np.array([now, Timedelta("1D"), np.timedelta64(2, "h")]) msg = r"unsupported operand type\(s\) for \-: 'Timedelta' and 'Timestamp'" with pytest.raises(TypeError, match=msg): Timedelta("1D") - arr @pytest.mark.parametrize("op", [operator.add, ops.radd]) def test_td_add_timedeltalike_object_dtype_array(self, op): # GH#21980 arr = np.array( [Timestamp("20130101 9:01"), Timestamp("20121230 9:02")]) exp = np.array( [Timestamp("20130102 9:01"), Timestamp("20121231 9:02")]) res = op(arr, Timedelta("1D")) tm.assert_numpy_array_equal(res, exp) @pytest.mark.parametrize("op", [operator.add, ops.radd]) def test_td_add_mixed_timedeltalike_object_dtype_array(self, op): # GH#21980 now = Timestamp.now() arr = np.array([now, Timedelta("1D")]) exp = np.array([now + Timedelta("1D"), Timedelta("2D")]) res = op(arr, Timedelta("1D")) tm.assert_numpy_array_equal(res, exp) # TODO: moved from index tests following #24365, may need de-duplication def test_ops_ndarray(self): td = Timedelta("1 day") # timedelta, timedelta other = pd.to_timedelta(["1 day"]).values expected = pd.to_timedelta(["2 days"]).values tm.assert_numpy_array_equal(td + other, expected) tm.assert_numpy_array_equal(other + td, expected) msg = r"unsupported operand type\(s\) for \+: 'Timedelta' and 'int'" with pytest.raises(TypeError, match=msg): td + np.array([1]) msg = ( r"unsupported operand type\(s\) for \+: 'numpy.ndarray' and 'Timedelta'|" "Concatenation operation is not implemented for NumPy arrays") with pytest.raises(TypeError, match=msg): np.array([1]) + td expected = pd.to_timedelta(["0 days"]).values tm.assert_numpy_array_equal(td - other, expected) tm.assert_numpy_array_equal(-other + td, expected) msg = r"unsupported operand type\(s\) for -: 'Timedelta' and 'int'" with pytest.raises(TypeError, match=msg): td - np.array([1]) msg = r"unsupported operand type\(s\) for -: 'numpy.ndarray' and 'Timedelta'" with pytest.raises(TypeError, match=msg): np.array([1]) - td expected = pd.to_timedelta(["2 days"]).values tm.assert_numpy_array_equal(td * np.array([2]), expected) tm.assert_numpy_array_equal(np.array([2]) * td, expected) msg = ("ufunc '?multiply'? cannot use operands with types " r"dtype\('<m8\[ns\]'\) and dtype\('<m8\[ns\]'\)") with pytest.raises(TypeError, match=msg): td * other with pytest.raises(TypeError, match=msg): other * td tm.assert_numpy_array_equal(td / other, np.array([1], dtype=np.float64)) tm.assert_numpy_array_equal(other / td, np.array([1], dtype=np.float64)) # timedelta, datetime other = pd.to_datetime(["2000-01-01"]).values expected = pd.to_datetime(["2000-01-02"]).values tm.assert_numpy_array_equal(td + other, expected) tm.assert_numpy_array_equal(other + td, expected) expected = pd.to_datetime(["1999-12-31"]).values tm.assert_numpy_array_equal(-td + other, expected) tm.assert_numpy_array_equal(other - td, expected)
def test_rounding_on_int_unit_construction(self, unit, value, expected): # GH 12690 result = Timedelta(value, unit=unit) assert result.value == expected result = Timedelta(str(value) + unit) assert result.value == expected
def test_fields(self): def check(value): # that we are int assert isinstance(value, int) # compat to datetime.timedelta rng = to_timedelta("1 days, 10:11:12") assert rng.days == 1 assert rng.seconds == 10 * 3600 + 11 * 60 + 12 assert rng.microseconds == 0 assert rng.nanoseconds == 0 msg = "'Timedelta' object has no attribute '{}'" with pytest.raises(AttributeError, match=msg.format("hours")): rng.hours with pytest.raises(AttributeError, match=msg.format("minutes")): rng.minutes with pytest.raises(AttributeError, match=msg.format("milliseconds")): rng.milliseconds # GH 10050 check(rng.days) check(rng.seconds) check(rng.microseconds) check(rng.nanoseconds) td = Timedelta("-1 days, 10:11:12") assert abs(td) == Timedelta("13:48:48") assert str(td) == "-1 days +10:11:12" assert -td == Timedelta("0 days 13:48:48") assert -Timedelta("-1 days, 10:11:12").value == 49728000000000 assert Timedelta("-1 days, 10:11:12").value == -49728000000000 rng = to_timedelta("-1 days, 10:11:12.100123456") assert rng.days == -1 assert rng.seconds == 10 * 3600 + 11 * 60 + 12 assert rng.microseconds == 100 * 1000 + 123 assert rng.nanoseconds == 456 msg = "'Timedelta' object has no attribute '{}'" with pytest.raises(AttributeError, match=msg.format("hours")): rng.hours with pytest.raises(AttributeError, match=msg.format("minutes")): rng.minutes with pytest.raises(AttributeError, match=msg.format("milliseconds")): rng.milliseconds # components tup = to_timedelta(-1, "us").components assert tup.days == -1 assert tup.hours == 23 assert tup.minutes == 59 assert tup.seconds == 59 assert tup.milliseconds == 999 assert tup.microseconds == 999 assert tup.nanoseconds == 0 # GH 10050 check(tup.days) check(tup.hours) check(tup.minutes) check(tup.seconds) check(tup.milliseconds) check(tup.microseconds) check(tup.nanoseconds) tup = Timedelta("-1 days 1 us").components assert tup.days == -2 assert tup.hours == 23 assert tup.minutes == 59 assert tup.seconds == 59 assert tup.milliseconds == 999 assert tup.microseconds == 999 assert tup.nanoseconds == 0
tm.assert_frame_equal(result, expected) # prod result = df.groupby(pd.cut(df["a"], grps), observed=observed)._cython_agg_general( "prod" ) expected = pd.DataFrame( {"a": [1, 1, 1716, 1]}, index=pd.CategoricalIndex(intervals, name="a", ordered=True), ) if observed: expected = expected[expected.a != 1] tm.assert_frame_equal(result, expected) @pytest.mark.parametrize("op", ["first", "last", "max", "min"]) @pytest.mark.parametrize( "data", [Timestamp("2016-10-14 21:00:44.557"), Timedelta("17088 days 21:00:44.557")] ) def test_cython_with_timestamp_and_nat(op, data): # https://github.com/pandas-dev/pandas/issues/19526 df = DataFrame({"a": [0, 1], "b": [data, NaT]}) index = Index([0, 1], name="a") # We will group by a and test the cython aggregations expected = DataFrame({"b": [data, NaT]}, index=index) result = df.groupby("a").aggregate(op) tm.assert_frame_equal(expected, result)
assert Timedelta(days=1, microseconds=6).resolution_string == "U" assert Timedelta(days=1, nanoseconds=6).resolution_string == "N" def test_resolution_deprecated(self): # GH#21344 td = Timedelta(days=4, hours=3) result = td.resolution assert result == Timedelta(nanoseconds=1) # Check that the attribute is available on the class, mirroring # the stdlib timedelta behavior result = Timedelta.resolution assert result == Timedelta(nanoseconds=1) @pytest.mark.parametrize( "value, expected", [ (Timedelta("10S"), True), (Timedelta("-10S"), True), (Timedelta(10, unit="ns"), True), (Timedelta(0, unit="ns"), False), (Timedelta(-10, unit="ns"), True), (Timedelta(None), True), (NaT, True), ], ) def test_truthiness(value, expected): # https://github.com/pandas-dev/pandas/issues/21484 assert bool(value) is expected
ts.to_period("D") def test_to_numpy_alias(self): # GH 24653: alias .to_numpy() for scalars ts = Timestamp(datetime.now()) assert ts.to_datetime64() == ts.to_numpy() class SubDatetime(datetime): pass @pytest.mark.parametrize( "lh,rh", [ (SubDatetime(2000, 1, 1), Timedelta(hours=1)), (Timedelta(hours=1), SubDatetime(2000, 1, 1)), ], ) def test_dt_subclass_add_timedelta(lh, rh): # GH#25851 # ensure that subclassed datetime works for # Timedelta operations result = lh + rh expected = SubDatetime(2000, 1, 1, 1) assert result == expected def test_constructor_ambigous_dst(): # GH 24329 # Make sure that calling Timestamp constructor
def test_value_counts_datetime64(index_or_series): klass = index_or_series # GH 3002, datetime64[ns] # don't test names though txt = "\n".join([ "xxyyzz20100101PIE", "xxyyzz20100101GUM", "xxyyzz20100101EGG", "xxyyww20090101EGG", "foofoo20080909PIE", "foofoo20080909GUM", ]) f = StringIO(txt) df = pd.read_fwf(f, widths=[6, 8, 3], names=["person_id", "dt", "food"], parse_dates=["dt"]) s = klass(df["dt"].copy()) s.name = None idx = pd.to_datetime( ["2010-01-01 00:00:00", "2008-09-09 00:00:00", "2009-01-01 00:00:00"]) expected_s = Series([3, 2, 1], index=idx) tm.assert_series_equal(s.value_counts(), expected_s) expected = np_array_datetime64_compat( ["2010-01-01 00:00:00", "2009-01-01 00:00:00", "2008-09-09 00:00:00"], dtype="datetime64[ns]", ) if isinstance(s, Index): tm.assert_index_equal(s.unique(), DatetimeIndex(expected)) else: tm.assert_numpy_array_equal(s.unique(), expected) assert s.nunique() == 3 # with NaT s = df["dt"].copy() s = klass(list(s.values) + [pd.NaT]) result = s.value_counts() assert result.index.dtype == "datetime64[ns]" tm.assert_series_equal(result, expected_s) result = s.value_counts(dropna=False) expected_s[pd.NaT] = 1 tm.assert_series_equal(result, expected_s) unique = s.unique() assert unique.dtype == "datetime64[ns]" # numpy_array_equal cannot compare pd.NaT if isinstance(s, Index): exp_idx = DatetimeIndex(expected.tolist() + [pd.NaT]) tm.assert_index_equal(unique, exp_idx) else: tm.assert_numpy_array_equal(unique[:3], expected) assert pd.isna(unique[3]) assert s.nunique() == 3 assert s.nunique(dropna=False) == 4 # timedelta64[ns] td = df.dt - df.dt + timedelta(1) td = klass(td, name="dt") result = td.value_counts() expected_s = Series([6], index=[Timedelta("1day")], name="dt") tm.assert_series_equal(result, expected_s) expected = TimedeltaIndex(["1 days"], name="dt") if isinstance(td, Index): tm.assert_index_equal(td.unique(), expected) else: tm.assert_numpy_array_equal(td.unique(), expected.values) td2 = timedelta(1) + (df.dt - df.dt) td2 = klass(td2, name="dt") result2 = td2.value_counts() tm.assert_series_equal(result2, expected_s)
def test_td_floordiv_numeric_series(self): # GH#18846 td = Timedelta(hours=3, minutes=4) ser = pd.Series([1], dtype=np.int64) res = td // ser assert res.dtype.kind == "m"
def test_td_rfloordiv_null_scalar(self): # GH#18846 td = Timedelta(hours=3, minutes=3) assert np.isnan(td.__rfloordiv__(NaT)) assert np.isnan(td.__rfloordiv__(np.timedelta64("NaT")))
def test_td_mul_nan(self, op, nan): # np.float64('NaN') has a 'dtype' attr, avoid treating as array td = Timedelta(10, unit="d") result = op(td, nan) assert result is NaT
def test_td_floordiv_offsets(self): # GH#19738 td = Timedelta(hours=3, minutes=4) assert td // offsets.Hour(1) == 3 assert td // offsets.Minute(2) == 92
class TestTimedeltaMultiplicationDivision: """ Tests for Timedelta methods: __mul__, __rmul__, __div__, __rdiv__, __truediv__, __rtruediv__, __floordiv__, __rfloordiv__, __mod__, __rmod__, __divmod__, __rdivmod__ """ # --------------------------------------------------------------- # Timedelta.__mul__, __rmul__ @pytest.mark.parametrize( "td_nat", [NaT, np.timedelta64("NaT", "ns"), np.timedelta64("NaT")]) @pytest.mark.parametrize("op", [operator.mul, ops.rmul]) def test_td_mul_nat(self, op, td_nat): # GH#19819 td = Timedelta(10, unit="d") typs = "|".join(["numpy.timedelta64", "NaTType", "Timedelta"]) msg = "|".join([ rf"unsupported operand type\(s\) for \*: '{typs}' and '{typs}'", r"ufunc '?multiply'? cannot use operands with types", ]) with pytest.raises(TypeError, match=msg): op(td, td_nat) @pytest.mark.parametrize("nan", [np.nan, np.float64("NaN"), float("nan")]) @pytest.mark.parametrize("op", [operator.mul, ops.rmul]) def test_td_mul_nan(self, op, nan): # np.float64('NaN') has a 'dtype' attr, avoid treating as array td = Timedelta(10, unit="d") result = op(td, nan) assert result is NaT @pytest.mark.parametrize("op", [operator.mul, ops.rmul]) def test_td_mul_scalar(self, op): # GH#19738 td = Timedelta(minutes=3) result = op(td, 2) assert result == Timedelta(minutes=6) result = op(td, 1.5) assert result == Timedelta(minutes=4, seconds=30) assert op(td, np.nan) is NaT assert op(-1, td).value == -1 * td.value assert op(-1.0, td).value == -1.0 * td.value msg = "unsupported operand type" with pytest.raises(TypeError, match=msg): # timedelta * datetime is gibberish op(td, Timestamp(2016, 1, 2)) with pytest.raises(TypeError, match=msg): # invalid multiply with another timedelta op(td, td) # --------------------------------------------------------------- # Timedelta.__div__, __truediv__ def test_td_div_timedeltalike_scalar(self): # GH#19738 td = Timedelta(10, unit="d") result = td / offsets.Hour(1) assert result == 240 assert td / td == 1 assert td / np.timedelta64(60, "h") == 4 assert np.isnan(td / NaT) def test_td_div_td64_non_nano(self): # truediv td = Timedelta("1 days 2 hours 3 ns") result = td / np.timedelta64(1, "D") assert result == td.value / float(86400 * 1e9) result = td / np.timedelta64(1, "s") assert result == td.value / float(1e9) result = td / np.timedelta64(1, "ns") assert result == td.value # floordiv td = Timedelta("1 days 2 hours 3 ns") result = td // np.timedelta64(1, "D") assert result == 1 result = td // np.timedelta64(1, "s") assert result == 93600 result = td // np.timedelta64(1, "ns") assert result == td.value def test_td_div_numeric_scalar(self): # GH#19738 td = Timedelta(10, unit="d") result = td / 2 assert isinstance(result, Timedelta) assert result == Timedelta(days=5) result = td / 5.0 assert isinstance(result, Timedelta) assert result == Timedelta(days=2) @pytest.mark.parametrize( "nan", [ np.nan, pytest.param( np.float64("NaN"), marks=pytest.mark.xfail( # Works on numpy dev only in python 3.9 is_numpy_dev and not compat.PY39, raises=RuntimeWarning, reason="https://github.com/pandas-dev/pandas/issues/31992", ), ), float("nan"), ], ) def test_td_div_nan(self, nan): # np.float64('NaN') has a 'dtype' attr, avoid treating as array td = Timedelta(10, unit="d") result = td / nan assert result is NaT result = td // nan assert result is NaT # --------------------------------------------------------------- # Timedelta.__rdiv__ def test_td_rdiv_timedeltalike_scalar(self): # GH#19738 td = Timedelta(10, unit="d") result = offsets.Hour(1) / td assert result == 1 / 240.0 assert np.timedelta64(60, "h") / td == 0.25 def test_td_rdiv_na_scalar(self): # GH#31869 None gets cast to NaT td = Timedelta(10, unit="d") result = NaT / td assert np.isnan(result) result = None / td assert np.isnan(result) result = np.timedelta64("NaT") / td assert np.isnan(result) msg = r"unsupported operand type\(s\) for /: 'numpy.datetime64' and 'Timedelta'" with pytest.raises(TypeError, match=msg): np.datetime64("NaT") / td msg = r"unsupported operand type\(s\) for /: 'float' and 'Timedelta'" with pytest.raises(TypeError, match=msg): np.nan / td def test_td_rdiv_ndarray(self): td = Timedelta(10, unit="d") arr = np.array([td], dtype=object) result = arr / td expected = np.array([1], dtype=np.float64) tm.assert_numpy_array_equal(result, expected) arr = np.array([None]) result = arr / td expected = np.array([np.nan]) tm.assert_numpy_array_equal(result, expected) arr = np.array([np.nan], dtype=object) msg = r"unsupported operand type\(s\) for /: 'float' and 'Timedelta'" with pytest.raises(TypeError, match=msg): arr / td arr = np.array([np.nan], dtype=np.float64) msg = "cannot use operands with types dtype" with pytest.raises(TypeError, match=msg): arr / td # --------------------------------------------------------------- # Timedelta.__floordiv__ def test_td_floordiv_timedeltalike_scalar(self): # GH#18846 td = Timedelta(hours=3, minutes=4) scalar = Timedelta(hours=3, minutes=3) assert td // scalar == 1 assert -td // scalar.to_pytimedelta() == -2 assert (2 * td) // scalar.to_timedelta64() == 2 def test_td_floordiv_null_scalar(self): # GH#18846 td = Timedelta(hours=3, minutes=4) assert td // np.nan is NaT assert np.isnan(td // NaT) assert np.isnan(td // np.timedelta64("NaT")) def test_td_floordiv_offsets(self): # GH#19738 td = Timedelta(hours=3, minutes=4) assert td // offsets.Hour(1) == 3 assert td // offsets.Minute(2) == 92 def test_td_floordiv_invalid_scalar(self): # GH#18846 td = Timedelta(hours=3, minutes=4) msg = "|".join([ r"Invalid dtype datetime64\[D\] for __floordiv__", "'dtype' is an invalid keyword argument for this function", r"ufunc '?floor_divide'? cannot use operands with types", ]) with pytest.raises(TypeError, match=msg): td // np.datetime64("2016-01-01", dtype="datetime64[us]") def test_td_floordiv_numeric_scalar(self): # GH#18846 td = Timedelta(hours=3, minutes=4) expected = Timedelta(hours=1, minutes=32) assert td // 2 == expected assert td // 2.0 == expected assert td // np.float64(2.0) == expected assert td // np.int32(2.0) == expected assert td // np.uint8(2.0) == expected def test_td_floordiv_timedeltalike_array(self): # GH#18846 td = Timedelta(hours=3, minutes=4) scalar = Timedelta(hours=3, minutes=3) # Array-like others assert td // np.array(scalar.to_timedelta64()) == 1 res = (3 * td) // np.array([scalar.to_timedelta64()]) expected = np.array([3], dtype=np.int64) tm.assert_numpy_array_equal(res, expected) res = (10 * td) // np.array( [scalar.to_timedelta64(), np.timedelta64("NaT")]) expected = np.array([10, np.nan]) tm.assert_numpy_array_equal(res, expected) def test_td_floordiv_numeric_series(self): # GH#18846 td = Timedelta(hours=3, minutes=4) ser = pd.Series([1], dtype=np.int64) res = td // ser assert res.dtype.kind == "m" # --------------------------------------------------------------- # Timedelta.__rfloordiv__ def test_td_rfloordiv_timedeltalike_scalar(self): # GH#18846 td = Timedelta(hours=3, minutes=3) scalar = Timedelta(hours=3, minutes=4) # scalar others # x // Timedelta is defined only for timedelta-like x. int-like, # float-like, and date-like, in particular, should all either # a) raise TypeError directly or # b) return NotImplemented, following which the reversed # operation will raise TypeError. assert td.__rfloordiv__(scalar) == 1 assert (-td).__rfloordiv__(scalar.to_pytimedelta()) == -2 assert (2 * td).__rfloordiv__(scalar.to_timedelta64()) == 0 def test_td_rfloordiv_null_scalar(self): # GH#18846 td = Timedelta(hours=3, minutes=3) assert np.isnan(td.__rfloordiv__(NaT)) assert np.isnan(td.__rfloordiv__(np.timedelta64("NaT"))) def test_td_rfloordiv_offsets(self): # GH#19738 assert offsets.Hour(1) // Timedelta(minutes=25) == 2 def test_td_rfloordiv_invalid_scalar(self): # GH#18846 td = Timedelta(hours=3, minutes=3) dt64 = np.datetime64("2016-01-01", "us") assert td.__rfloordiv__(dt64) is NotImplemented msg = ( r"unsupported operand type\(s\) for //: 'numpy.datetime64' and 'Timedelta'" ) with pytest.raises(TypeError, match=msg): dt64 // td def test_td_rfloordiv_numeric_scalar(self): # GH#18846 td = Timedelta(hours=3, minutes=3) assert td.__rfloordiv__(np.nan) is NotImplemented assert td.__rfloordiv__(3.5) is NotImplemented assert td.__rfloordiv__(2) is NotImplemented assert td.__rfloordiv__(np.float64(2.0)) is NotImplemented assert td.__rfloordiv__(np.uint8(9)) is NotImplemented assert td.__rfloordiv__(np.int32(2.0)) is NotImplemented msg = r"unsupported operand type\(s\) for //: '.*' and 'Timedelta" with pytest.raises(TypeError, match=msg): np.float64(2.0) // td with pytest.raises(TypeError, match=msg): np.uint8(9) // td with pytest.raises(TypeError, match=msg): # deprecated GH#19761, enforced GH#29797 np.int32(2.0) // td def test_td_rfloordiv_timedeltalike_array(self): # GH#18846 td = Timedelta(hours=3, minutes=3) scalar = Timedelta(hours=3, minutes=4) # Array-like others assert td.__rfloordiv__(np.array(scalar.to_timedelta64())) == 1 res = td.__rfloordiv__(np.array([(3 * scalar).to_timedelta64()])) expected = np.array([3], dtype=np.int64) tm.assert_numpy_array_equal(res, expected) arr = np.array([(10 * scalar).to_timedelta64(), np.timedelta64("NaT")]) res = td.__rfloordiv__(arr) expected = np.array([10, np.nan]) tm.assert_numpy_array_equal(res, expected) def test_td_rfloordiv_intarray(self): # deprecated GH#19761, enforced GH#29797 ints = np.array([1349654400, 1349740800, 1349827200, 1349913600 ]) * 10**9 msg = "Invalid dtype" with pytest.raises(TypeError, match=msg): ints // Timedelta(1, unit="s") def test_td_rfloordiv_numeric_series(self): # GH#18846 td = Timedelta(hours=3, minutes=3) ser = pd.Series([1], dtype=np.int64) res = td.__rfloordiv__(ser) assert res is NotImplemented msg = "Invalid dtype" with pytest.raises(TypeError, match=msg): # Deprecated GH#19761, enforced GH#29797 ser // td # ---------------------------------------------------------------- # Timedelta.__mod__, __rmod__ def test_mod_timedeltalike(self): # GH#19365 td = Timedelta(hours=37) # Timedelta-like others result = td % Timedelta(hours=6) assert isinstance(result, Timedelta) assert result == Timedelta(hours=1) result = td % timedelta(minutes=60) assert isinstance(result, Timedelta) assert result == Timedelta(0) result = td % NaT assert result is NaT def test_mod_timedelta64_nat(self): # GH#19365 td = Timedelta(hours=37) result = td % np.timedelta64("NaT", "ns") assert result is NaT def test_mod_timedelta64(self): # GH#19365 td = Timedelta(hours=37) result = td % np.timedelta64(2, "h") assert isinstance(result, Timedelta) assert result == Timedelta(hours=1) def test_mod_offset(self): # GH#19365 td = Timedelta(hours=37) result = td % offsets.Hour(5) assert isinstance(result, Timedelta) assert result == Timedelta(hours=2) def test_mod_numeric(self): # GH#19365 td = Timedelta(hours=37) # Numeric Others result = td % 2 assert isinstance(result, Timedelta) assert result == Timedelta(0) result = td % 1e12 assert isinstance(result, Timedelta) assert result == Timedelta(minutes=3, seconds=20) result = td % int(1e12) assert isinstance(result, Timedelta) assert result == Timedelta(minutes=3, seconds=20) def test_mod_invalid(self): # GH#19365 td = Timedelta(hours=37) msg = "unsupported operand type" with pytest.raises(TypeError, match=msg): td % Timestamp("2018-01-22") with pytest.raises(TypeError, match=msg): td % [] def test_rmod_pytimedelta(self): # GH#19365 td = Timedelta(minutes=3) result = timedelta(minutes=4) % td assert isinstance(result, Timedelta) assert result == Timedelta(minutes=1) def test_rmod_timedelta64(self): # GH#19365 td = Timedelta(minutes=3) result = np.timedelta64(5, "m") % td assert isinstance(result, Timedelta) assert result == Timedelta(minutes=2) def test_rmod_invalid(self): # GH#19365 td = Timedelta(minutes=3) msg = "unsupported operand" with pytest.raises(TypeError, match=msg): Timestamp("2018-01-22") % td with pytest.raises(TypeError, match=msg): 15 % td with pytest.raises(TypeError, match=msg): 16.0 % td msg = "Invalid dtype int" with pytest.raises(TypeError, match=msg): np.array([22, 24]) % td # ---------------------------------------------------------------- # Timedelta.__divmod__, __rdivmod__ def test_divmod_numeric(self): # GH#19365 td = Timedelta(days=2, hours=6) result = divmod(td, 53 * 3600 * 1e9) assert result[0] == Timedelta(1, unit="ns") assert isinstance(result[1], Timedelta) assert result[1] == Timedelta(hours=1) assert result result = divmod(td, np.nan) assert result[0] is NaT assert result[1] is NaT def test_divmod(self): # GH#19365 td = Timedelta(days=2, hours=6) result = divmod(td, timedelta(days=1)) assert result[0] == 2 assert isinstance(result[1], Timedelta) assert result[1] == Timedelta(hours=6) result = divmod(td, 54) assert result[0] == Timedelta(hours=1) assert isinstance(result[1], Timedelta) assert result[1] == Timedelta(0) result = divmod(td, NaT) assert np.isnan(result[0]) assert result[1] is NaT def test_divmod_offset(self): # GH#19365 td = Timedelta(days=2, hours=6) result = divmod(td, offsets.Hour(-4)) assert result[0] == -14 assert isinstance(result[1], Timedelta) assert result[1] == Timedelta(hours=-2) def test_divmod_invalid(self): # GH#19365 td = Timedelta(days=2, hours=6) msg = r"unsupported operand type\(s\) for //: 'Timedelta' and 'Timestamp'" with pytest.raises(TypeError, match=msg): divmod(td, Timestamp("2018-01-22")) def test_rdivmod_pytimedelta(self): # GH#19365 result = divmod(timedelta(days=2, hours=6), Timedelta(days=1)) assert result[0] == 2 assert isinstance(result[1], Timedelta) assert result[1] == Timedelta(hours=6) def test_rdivmod_offset(self): result = divmod(offsets.Hour(54), Timedelta(hours=-4)) assert result[0] == -14 assert isinstance(result[1], Timedelta) assert result[1] == Timedelta(hours=-2) def test_rdivmod_invalid(self): # GH#19365 td = Timedelta(minutes=3) msg = "unsupported operand type" with pytest.raises(TypeError, match=msg): divmod(Timestamp("2018-01-22"), td) with pytest.raises(TypeError, match=msg): divmod(15, td) with pytest.raises(TypeError, match=msg): divmod(16.0, td) msg = "Invalid dtype int" with pytest.raises(TypeError, match=msg): divmod(np.array([22, 24]), td) # ---------------------------------------------------------------- @pytest.mark.parametrize( "op", [operator.mul, ops.rmul, operator.truediv, ops.rdiv, ops.rsub]) @pytest.mark.parametrize( "arr", [ np.array([Timestamp("20130101 9:01"), Timestamp("20121230 9:02")]), np.array([Timestamp.now(), Timedelta("1D")]), ], ) def test_td_op_timedelta_timedeltalike_array(self, op, arr): msg = "unsupported operand type|cannot use operands with types" with pytest.raises(TypeError, match=msg): op(arr, Timedelta("1D"))
def test_td_rsub_offset(self): result = offsets.Hour(1) - Timedelta(10, unit="d") assert isinstance(result, Timedelta) assert result == Timedelta(-239, unit="h")
def test_td_sub_offset(self): td = Timedelta(10, unit="d") result = td - offsets.Hour(1) assert isinstance(result, Timedelta) assert result == Timedelta(239, unit="h")
def test_timedelta_ops(self): # GH#4984 # make sure ops return Timedelta s = Series([ Timestamp("20130101") + timedelta(seconds=i * i) for i in range(10) ]) td = s.diff() result = td.mean() expected = to_timedelta(timedelta(seconds=9)) assert result == expected result = td.to_frame().mean() assert result[0] == expected result = td.quantile(0.1) expected = Timedelta(np.timedelta64(2600, "ms")) assert result == expected result = td.median() expected = to_timedelta("00:00:09") assert result == expected result = td.to_frame().median() assert result[0] == expected # GH#6462 # consistency in returned values for sum result = td.sum() expected = to_timedelta("00:01:21") assert result == expected result = td.to_frame().sum() assert result[0] == expected # std result = td.std() expected = to_timedelta(Series(td.dropna().values).std()) assert result == expected result = td.to_frame().std() assert result[0] == expected # invalid ops for op in ["skew", "kurt", "sem", "prod", "var"]: msg = "reduction operation '{}' not allowed for this dtype" with pytest.raises(TypeError, match=msg.format(op)): getattr(td, op)() with pytest.raises(TypeError, match=msg.format(op)): getattr(td.to_frame(), op)(numeric_only=False) # GH#10040 # make sure NaT is properly handled by median() s = Series([Timestamp("2015-02-03"), Timestamp("2015-02-07")]) assert s.diff().median() == timedelta(days=4) s = Series([ Timestamp("2015-02-03"), Timestamp("2015-02-07"), Timestamp("2015-02-15") ]) assert s.diff().median() == timedelta(days=6)
def test_td_rfloordiv_offsets(self): # GH#19738 assert offsets.Hour(1) // Timedelta(minutes=25) == 2
tm.assert_frame_equal(result, expected) # prod result = df.groupby(pd.cut(df['a'], grps), observed=observed)._cython_agg_general('prod') expected = pd.DataFrame({"a": [1, 1, 1716, 1]}, index=pd.CategoricalIndex(intervals, name='a', ordered=True)) if observed: expected = expected[expected.a != 1] tm.assert_frame_equal(result, expected) @pytest.mark.parametrize('op', ['first', 'last', 'max', 'min']) @pytest.mark.parametrize('data', [ Timestamp('2016-10-14 21:00:44.557'), Timedelta('17088 days 21:00:44.557'), ]) def test_cython_with_timestamp_and_nat(op, data): # https://github.com/pandas-dev/pandas/issues/19526 df = DataFrame({'a': [0, 1], 'b': [data, NaT]}) index = Index([0, 1], name='a') # We will group by a and test the cython aggregations expected = DataFrame({'b': [data, NaT]}, index=index) result = df.groupby('a').aggregate(op) tm.assert_frame_equal(expected, result)
def test_mod_timedelta64_nat(self): # GH#19365 td = Timedelta(hours=37) result = td % np.timedelta64("NaT", "ns") assert result is NaT
def test_constructor_nanosecond(self, result): # GH 18898 expected = Timestamp(datetime(2000, 1, 2, 3, 4, 5, 6), tz=result.tz) expected = expected + Timedelta(nanoseconds=1) assert result == expected
def test_rmod_timedelta64(self): # GH#19365 td = Timedelta(minutes=3) result = np.timedelta64(5, "m") % td assert isinstance(result, Timedelta) assert result == Timedelta(minutes=2)
def test_value_counts_datetime64(self): klasses = [Index, Series] for klass in klasses: # GH 3002, datetime64[ns] # don't test names though txt = "\n".join([ 'xxyyzz20100101PIE', 'xxyyzz20100101GUM', 'xxyyzz20100101EGG', 'xxyyww20090101EGG', 'foofoo20080909PIE', 'foofoo20080909GUM' ]) f = StringIO(txt) df = pd.read_fwf(f, widths=[6, 8, 3], names=["person_id", "dt", "food"], parse_dates=["dt"]) s = klass(df['dt'].copy()) s.name = None idx = pd.to_datetime([ '2010-01-01 00:00:00Z', '2008-09-09 00:00:00Z', '2009-01-01 00:00:00X' ]) expected_s = Series([3, 2, 1], index=idx) tm.assert_series_equal(s.value_counts(), expected_s) expected = np_array_datetime64_compat([ '2010-01-01 00:00:00Z', '2009-01-01 00:00:00Z', '2008-09-09 00:00:00Z' ], dtype='datetime64[ns]') if isinstance(s, Index): tm.assert_index_equal(s.unique(), DatetimeIndex(expected)) else: tm.assert_numpy_array_equal(s.unique(), expected) self.assertEqual(s.nunique(), 3) # with NaT s = df['dt'].copy() s = klass([v for v in s.values] + [pd.NaT]) result = s.value_counts() self.assertEqual(result.index.dtype, 'datetime64[ns]') tm.assert_series_equal(result, expected_s) result = s.value_counts(dropna=False) expected_s[pd.NaT] = 1 tm.assert_series_equal(result, expected_s) unique = s.unique() self.assertEqual(unique.dtype, 'datetime64[ns]') # numpy_array_equal cannot compare pd.NaT if isinstance(s, Index): exp_idx = DatetimeIndex(expected.tolist() + [pd.NaT]) tm.assert_index_equal(unique, exp_idx) else: tm.assert_numpy_array_equal(unique[:3], expected) self.assertTrue(pd.isnull(unique[3])) self.assertEqual(s.nunique(), 3) self.assertEqual(s.nunique(dropna=False), 4) # timedelta64[ns] td = df.dt - df.dt + timedelta(1) td = klass(td, name='dt') result = td.value_counts() expected_s = Series([6], index=[Timedelta('1day')], name='dt') tm.assert_series_equal(result, expected_s) expected = TimedeltaIndex(['1 days'], name='dt') if isinstance(td, Index): tm.assert_index_equal(td.unique(), expected) else: tm.assert_numpy_array_equal(td.unique(), expected.values) td2 = timedelta(1) + (df.dt - df.dt) td2 = klass(td2, name='dt') result2 = td2.value_counts() tm.assert_series_equal(result2, expected_s)
def test_rdivmod_pytimedelta(self): # GH#19365 result = divmod(timedelta(days=2, hours=6), Timedelta(days=1)) assert result[0] == 2 assert isinstance(result[1], Timedelta) assert result[1] == Timedelta(hours=6)
def test_end_time(self): index = PeriodIndex(freq='M', start='2016-01-01', end='2016-05-31') expected_index = date_range('2016-01-01', end='2016-05-31', freq='M') expected_index += Timedelta(1, 'D') - Timedelta(1, 'ns') tm.assert_index_equal(index.end_time, expected_index)
def test_rdivmod_offset(self): result = divmod(offsets.Hour(54), Timedelta(hours=-4)) assert result[0] == -14 assert isinstance(result[1], Timedelta) assert result[1] == Timedelta(hours=-2)
def test_arithmetic_overflow(self): with pytest.raises(OverflowError): Timestamp("1700-01-01") + Timedelta(13 * 19999, unit="D") with pytest.raises(OverflowError): Timestamp("1700-01-01") + timedelta(days=13 * 19999)
def test_td_op_timedelta_timedeltalike_array(self, op, arr): msg = "unsupported operand type|cannot use operands with types" with pytest.raises(TypeError, match=msg): op(arr, Timedelta("1D"))
def test_array_timedelta_floordiv(self): # deprecated GH#19761, enforced GH#29797 ints = pd.date_range("2012-10-08", periods=4, freq="D").view("i8") with pytest.raises(TypeError, match="Invalid dtype"): ints // Timedelta(1, unit="s")
class TestReductions: @pytest.mark.parametrize("name", ["std", "min", "max", "median", "mean"]) @pytest.mark.parametrize("skipna", [True, False]) def test_reductions_empty(self, name, skipna): tdi = pd.TimedeltaIndex([]) arr = tdi.array result = getattr(tdi, name)(skipna=skipna) assert result is pd.NaT result = getattr(arr, name)(skipna=skipna) assert result is pd.NaT @pytest.mark.parametrize("skipna", [True, False]) def test_sum_empty(self, skipna): tdi = pd.TimedeltaIndex([]) arr = tdi.array result = tdi.sum(skipna=skipna) assert isinstance(result, Timedelta) assert result == Timedelta(0) result = arr.sum(skipna=skipna) assert isinstance(result, Timedelta) assert result == Timedelta(0) def test_min_max(self): arr = TimedeltaArray._from_sequence( ["3H", "3H", "NaT", "2H", "5H", "4H"]) result = arr.min() expected = Timedelta("2H") assert result == expected result = arr.max() expected = Timedelta("5H") assert result == expected result = arr.min(skipna=False) assert result is pd.NaT result = arr.max(skipna=False) assert result is pd.NaT def test_sum(self): tdi = pd.TimedeltaIndex(["3H", "3H", "NaT", "2H", "5H", "4H"]) arr = tdi.array result = arr.sum(skipna=True) expected = Timedelta(hours=17) assert isinstance(result, Timedelta) assert result == expected result = tdi.sum(skipna=True) assert isinstance(result, Timedelta) assert result == expected result = arr.sum(skipna=False) assert result is pd.NaT result = tdi.sum(skipna=False) assert result is pd.NaT result = arr.sum(min_count=9) assert result is pd.NaT result = tdi.sum(min_count=9) assert result is pd.NaT result = arr.sum(min_count=1) assert isinstance(result, Timedelta) assert result == expected result = tdi.sum(min_count=1) assert isinstance(result, Timedelta) assert result == expected def test_npsum(self): # GH#25282, GH#25335 np.sum should return a Timedelta, not timedelta64 tdi = pd.TimedeltaIndex(["3H", "3H", "2H", "5H", "4H"]) arr = tdi.array result = np.sum(tdi) expected = Timedelta(hours=17) assert isinstance(result, Timedelta) assert result == expected result = np.sum(arr) assert isinstance(result, Timedelta) assert result == expected def test_sum_2d_skipna_false(self): arr = np.arange(8).astype( np.int64).view("m8[s]").astype("m8[ns]").reshape(4, 2) arr[-1, -1] = "Nat" tda = TimedeltaArray(arr) result = tda.sum(skipna=False) assert result is pd.NaT result = tda.sum(axis=0, skipna=False) expected = pd.TimedeltaIndex([Timedelta(seconds=12), pd.NaT])._values tm.assert_timedelta_array_equal(result, expected) result = tda.sum(axis=1, skipna=False) expected = pd.TimedeltaIndex([ Timedelta(seconds=1), Timedelta(seconds=5), Timedelta(seconds=9), pd.NaT, ])._values tm.assert_timedelta_array_equal(result, expected) # Adding a Timestamp makes this a test for DatetimeArray.std @pytest.mark.parametrize( "add", [ Timedelta(0), pd.Timestamp.now(), pd.Timestamp.now("UTC"), pd.Timestamp.now("Asia/Tokyo"), ], ) def test_std(self, add): tdi = pd.TimedeltaIndex(["0H", "4H", "NaT", "4H", "0H", "2H"]) + add arr = tdi.array result = arr.std(skipna=True) expected = Timedelta(hours=2) assert isinstance(result, Timedelta) assert result == expected result = tdi.std(skipna=True) assert isinstance(result, Timedelta) assert result == expected if getattr(arr, "tz", None) is None: result = nanops.nanstd(np.asarray(arr), skipna=True) assert isinstance(result, Timedelta) assert result == expected result = arr.std(skipna=False) assert result is pd.NaT result = tdi.std(skipna=False) assert result is pd.NaT if getattr(arr, "tz", None) is None: result = nanops.nanstd(np.asarray(arr), skipna=False) assert result is pd.NaT def test_median(self): tdi = pd.TimedeltaIndex(["0H", "3H", "NaT", "5H06m", "0H", "2H"]) arr = tdi.array result = arr.median(skipna=True) expected = Timedelta(hours=2) assert isinstance(result, Timedelta) assert result == expected result = tdi.median(skipna=True) assert isinstance(result, Timedelta) assert result == expected result = arr.median(skipna=False) assert result is pd.NaT result = tdi.median(skipna=False) assert result is pd.NaT def test_mean(self): tdi = pd.TimedeltaIndex(["0H", "3H", "NaT", "5H06m", "0H", "2H"]) arr = tdi._data # manually verified result expected = Timedelta(arr.dropna()._ndarray.mean()) result = arr.mean() assert result == expected result = arr.mean(skipna=False) assert result is pd.NaT result = arr.dropna().mean(skipna=False) assert result == expected result = arr.mean(axis=0) assert result == expected def test_mean_2d(self): tdi = pd.timedelta_range("14 days", periods=6) tda = tdi._data.reshape(3, 2) result = tda.mean(axis=0) expected = tda[1] tm.assert_timedelta_array_equal(result, expected) result = tda.mean(axis=1) expected = tda[:, 0] + Timedelta(hours=12) tm.assert_timedelta_array_equal(result, expected) result = tda.mean(axis=None) expected = tdi.mean() assert result == expected
def test_iso_conversion(self): # GH #21877 expected = Timedelta(1, unit="s") assert to_timedelta("P0DT0H0M1S") == expected
def test_td_sub_nat(self): # In this context pd.NaT is treated as timedelta-like td = Timedelta(10, unit="d") result = td - NaT assert result is NaT