A PyQT GUI application for converting InfoLease report outputs into Excel files. Handles parsing and summarizing. Learns where files are meant to be store and compiles monthly and yearly summaries.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
InfoLeaseExtract/venv/Lib/site-packages/pandas/tests/scalar/timestamp/test_arithmetic.py

321 lines
11 KiB

from datetime import (
datetime,
timedelta,
timezone,
)
import numpy as np
import pytest
from pandas._libs.tslibs import (
OutOfBoundsDatetime,
Timedelta,
Timestamp,
offsets,
to_offset,
)
import pandas._testing as tm
class TestTimestampArithmetic:
def test_overflow_offset(self):
# no overflow expected
stamp = Timestamp("2000/1/1")
offset_no_overflow = to_offset("D") * 100
expected = Timestamp("2000/04/10")
assert stamp + offset_no_overflow == expected
assert offset_no_overflow + stamp == expected
expected = Timestamp("1999/09/23")
assert stamp - offset_no_overflow == expected
def test_overflow_offset_raises(self):
# xref https://github.com/statsmodels/statsmodels/issues/3374
# ends up multiplying really large numbers which overflow
stamp = Timestamp("2017-01-13 00:00:00")
offset_overflow = 20169940 * offsets.Day(1)
msg = (
"the add operation between "
r"\<-?\d+ \* Days\> and \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} "
"will overflow"
)
lmsg = "|".join(
["Python int too large to convert to C long", "int too big to convert"]
)
with pytest.raises(OverflowError, match=lmsg):
stamp + offset_overflow
with pytest.raises(OverflowError, match=msg):
offset_overflow + stamp
with pytest.raises(OverflowError, match=lmsg):
stamp - offset_overflow
# xref https://github.com/pandas-dev/pandas/issues/14080
# used to crash, so check for proper overflow exception
stamp = Timestamp("2000/1/1")
offset_overflow = to_offset("D") * 100**5
with pytest.raises(OverflowError, match=lmsg):
stamp + offset_overflow
with pytest.raises(OverflowError, match=msg):
offset_overflow + stamp
with pytest.raises(OverflowError, match=lmsg):
stamp - offset_overflow
def test_overflow_timestamp_raises(self):
# https://github.com/pandas-dev/pandas/issues/31774
msg = "Result is too large"
a = Timestamp("2101-01-01 00:00:00")
b = Timestamp("1688-01-01 00:00:00")
with pytest.raises(OutOfBoundsDatetime, match=msg):
a - b
# but we're OK for timestamp and datetime.datetime
assert (a - b.to_pydatetime()) == (a.to_pydatetime() - b)
def test_delta_preserve_nanos(self):
val = Timestamp(1337299200000000123)
result = val + timedelta(1)
assert result.nanosecond == val.nanosecond
def test_rsub_dtscalars(self, tz_naive_fixture):
# In particular, check that datetime64 - Timestamp works GH#28286
td = Timedelta(1235345642000)
ts = Timestamp("2021-01-01", tz=tz_naive_fixture)
other = ts + td
assert other - ts == td
assert other.to_pydatetime() - ts == td
if tz_naive_fixture is None:
assert other.to_datetime64() - ts == td
else:
msg = "Cannot subtract tz-naive and tz-aware datetime-like objects"
with pytest.raises(TypeError, match=msg):
other.to_datetime64() - ts
def test_timestamp_sub_datetime(self):
dt = datetime(2013, 10, 12)
ts = Timestamp(datetime(2013, 10, 13))
assert (ts - dt).days == 1
assert (dt - ts).days == -1
def test_subtract_tzaware_datetime(self):
t1 = Timestamp("2020-10-22T22:00:00+00:00")
t2 = datetime(2020, 10, 22, 22, tzinfo=timezone.utc)
result = t1 - t2
assert isinstance(result, Timedelta)
assert result == Timedelta("0 days")
def test_subtract_timestamp_from_different_timezone(self):
t1 = Timestamp("20130101").tz_localize("US/Eastern")
t2 = Timestamp("20130101").tz_localize("CET")
result = t1 - t2
assert isinstance(result, Timedelta)
assert result == Timedelta("0 days 06:00:00")
def test_subtracting_involving_datetime_with_different_tz(self):
t1 = datetime(2013, 1, 1, tzinfo=timezone(timedelta(hours=-5)))
t2 = Timestamp("20130101").tz_localize("CET")
result = t1 - t2
assert isinstance(result, Timedelta)
assert result == Timedelta("0 days 06:00:00")
result = t2 - t1
assert isinstance(result, Timedelta)
assert result == Timedelta("-1 days +18:00:00")
def test_subtracting_different_timezones(self, tz_aware_fixture):
t_raw = Timestamp("20130101")
t_UTC = t_raw.tz_localize("UTC")
t_diff = t_UTC.tz_convert(tz_aware_fixture) + Timedelta("0 days 05:00:00")
result = t_diff - t_UTC
assert isinstance(result, Timedelta)
assert result == Timedelta("0 days 05:00:00")
def test_addition_subtraction_types(self):
# Assert on the types resulting from Timestamp +/- various date/time
# objects
dt = datetime(2014, 3, 4)
td = timedelta(seconds=1)
# build a timestamp with a frequency, since then it supports
# addition/subtraction of integers
with tm.assert_produces_warning(FutureWarning, match="The 'freq' argument"):
# freq deprecated
ts = Timestamp(dt, freq="D")
msg = "Addition/subtraction of integers"
with pytest.raises(TypeError, match=msg):
# GH#22535 add/sub with integers is deprecated
ts + 1
with pytest.raises(TypeError, match=msg):
ts - 1
# Timestamp + datetime not supported, though subtraction is supported
# and yields timedelta more tests in tseries/base/tests/test_base.py
assert type(ts - dt) == Timedelta
assert type(ts + td) == Timestamp
assert type(ts - td) == Timestamp
# Timestamp +/- datetime64 not supported, so not tested (could possibly
# assert error raised?)
td64 = np.timedelta64(1, "D")
assert type(ts + td64) == Timestamp
assert type(ts - td64) == Timestamp
@pytest.mark.parametrize(
"freq, td, td64",
[
("S", timedelta(seconds=1), np.timedelta64(1, "s")),
("min", timedelta(minutes=1), np.timedelta64(1, "m")),
("H", timedelta(hours=1), np.timedelta64(1, "h")),
("D", timedelta(days=1), np.timedelta64(1, "D")),
("W", timedelta(weeks=1), np.timedelta64(1, "W")),
("M", None, np.timedelta64(1, "M")),
],
)
@pytest.mark.filterwarnings("ignore:Timestamp.freq is deprecated:FutureWarning")
@pytest.mark.filterwarnings("ignore:The 'freq' argument:FutureWarning")
def test_addition_subtraction_preserve_frequency(self, freq, td, td64):
ts = Timestamp("2014-03-05 00:00:00", freq=freq)
original_freq = ts.freq
assert (ts + 1 * original_freq).freq == original_freq
assert (ts - 1 * original_freq).freq == original_freq
if td is not None:
# timedelta does not support months as unit
assert (ts + td).freq == original_freq
assert (ts - td).freq == original_freq
assert (ts + td64).freq == original_freq
assert (ts - td64).freq == original_freq
@pytest.mark.parametrize(
"td", [Timedelta(hours=3), np.timedelta64(3, "h"), timedelta(hours=3)]
)
def test_radd_tdscalar(self, td, fixed_now_ts):
# GH#24775 timedelta64+Timestamp should not raise
ts = fixed_now_ts
assert td + ts == ts + td
@pytest.mark.parametrize(
"other,expected_difference",
[
(np.timedelta64(-123, "ns"), -123),
(np.timedelta64(1234567898, "ns"), 1234567898),
(np.timedelta64(-123, "us"), -123000),
(np.timedelta64(-123, "ms"), -123000000),
],
)
def test_timestamp_add_timedelta64_unit(self, other, expected_difference):
ts = Timestamp(datetime.utcnow())
result = ts + other
valdiff = result.value - ts.value
assert valdiff == expected_difference
@pytest.mark.parametrize(
"ts",
[
Timestamp("1776-07-04"),
Timestamp("1776-07-04", tz="UTC"),
],
)
@pytest.mark.parametrize(
"other",
[
1,
np.int64(1),
np.array([1, 2], dtype=np.int32),
np.array([3, 4], dtype=np.uint64),
],
)
def test_add_int_with_freq(self, ts, other):
msg = "Addition/subtraction of integers and integer-arrays"
with pytest.raises(TypeError, match=msg):
ts + other
with pytest.raises(TypeError, match=msg):
other + ts
with pytest.raises(TypeError, match=msg):
ts - other
msg = "unsupported operand type"
with pytest.raises(TypeError, match=msg):
other - ts
@pytest.mark.parametrize("shape", [(6,), (2, 3)])
def test_addsub_m8ndarray(self, shape):
# GH#33296
ts = Timestamp("2020-04-04 15:45")
other = np.arange(6).astype("m8[h]").reshape(shape)
result = ts + other
ex_stamps = [ts + Timedelta(hours=n) for n in range(6)]
expected = np.array([x.asm8 for x in ex_stamps], dtype="M8[ns]").reshape(shape)
tm.assert_numpy_array_equal(result, expected)
result = other + ts
tm.assert_numpy_array_equal(result, expected)
result = ts - other
ex_stamps = [ts - Timedelta(hours=n) for n in range(6)]
expected = np.array([x.asm8 for x in ex_stamps], dtype="M8[ns]").reshape(shape)
tm.assert_numpy_array_equal(result, expected)
msg = r"unsupported operand type\(s\) for -: 'numpy.ndarray' and 'Timestamp'"
with pytest.raises(TypeError, match=msg):
other - ts
@pytest.mark.parametrize("shape", [(6,), (2, 3)])
def test_addsub_m8ndarray_tzaware(self, shape):
# GH#33296
ts = Timestamp("2020-04-04 15:45", tz="US/Pacific")
other = np.arange(6).astype("m8[h]").reshape(shape)
result = ts + other
ex_stamps = [ts + Timedelta(hours=n) for n in range(6)]
expected = np.array(ex_stamps).reshape(shape)
tm.assert_numpy_array_equal(result, expected)
result = other + ts
tm.assert_numpy_array_equal(result, expected)
result = ts - other
ex_stamps = [ts - Timedelta(hours=n) for n in range(6)]
expected = np.array(ex_stamps).reshape(shape)
tm.assert_numpy_array_equal(result, expected)
msg = r"unsupported operand type\(s\) for -: 'numpy.ndarray' and 'Timestamp'"
with pytest.raises(TypeError, match=msg):
other - ts
def test_subtract_different_utc_objects(self, utc_fixture, utc_fixture2):
# GH 32619
dt = datetime(2021, 1, 1)
ts1 = Timestamp(dt, tz=utc_fixture)
ts2 = Timestamp(dt, tz=utc_fixture2)
result = ts1 - ts2
expected = Timedelta(0)
assert result == expected