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/tseries/offsets/test_offsets.py

866 lines
28 KiB

"""
Tests of pandas.tseries.offsets
"""
from __future__ import annotations
from datetime import (
datetime,
timedelta,
)
from typing import (
Dict,
List,
Tuple,
)
import numpy as np
import pytest
from pandas._libs.tslibs import (
NaT,
Timestamp,
conversion,
timezones,
)
import pandas._libs.tslibs.offsets as liboffsets
from pandas._libs.tslibs.offsets import (
_get_offset,
_offset_map,
)
from pandas._libs.tslibs.period import INVALID_FREQ_ERR_MSG
from pandas.errors import PerformanceWarning
from pandas import DatetimeIndex
import pandas._testing as tm
from pandas.tests.tseries.offsets.common import (
Base,
WeekDay,
)
import pandas.tseries.offsets as offsets
from pandas.tseries.offsets import (
FY5253,
BaseOffset,
BDay,
BMonthEnd,
BusinessHour,
CustomBusinessDay,
CustomBusinessHour,
CustomBusinessMonthBegin,
CustomBusinessMonthEnd,
DateOffset,
Easter,
FY5253Quarter,
LastWeekOfMonth,
MonthBegin,
Nano,
Tick,
Week,
WeekOfMonth,
)
_ApplyCases = List[Tuple[BaseOffset, Dict[datetime, datetime]]]
class TestCommon(Base):
# executed value created by Base._get_offset
# are applied to 2011/01/01 09:00 (Saturday)
# used for .apply and .rollforward
expecteds = {
"Day": Timestamp("2011-01-02 09:00:00"),
"DateOffset": Timestamp("2011-01-02 09:00:00"),
"BusinessDay": Timestamp("2011-01-03 09:00:00"),
"CustomBusinessDay": Timestamp("2011-01-03 09:00:00"),
"CustomBusinessMonthEnd": Timestamp("2011-01-31 09:00:00"),
"CustomBusinessMonthBegin": Timestamp("2011-01-03 09:00:00"),
"MonthBegin": Timestamp("2011-02-01 09:00:00"),
"BusinessMonthBegin": Timestamp("2011-01-03 09:00:00"),
"MonthEnd": Timestamp("2011-01-31 09:00:00"),
"SemiMonthEnd": Timestamp("2011-01-15 09:00:00"),
"SemiMonthBegin": Timestamp("2011-01-15 09:00:00"),
"BusinessMonthEnd": Timestamp("2011-01-31 09:00:00"),
"YearBegin": Timestamp("2012-01-01 09:00:00"),
"BYearBegin": Timestamp("2011-01-03 09:00:00"),
"YearEnd": Timestamp("2011-12-31 09:00:00"),
"BYearEnd": Timestamp("2011-12-30 09:00:00"),
"QuarterBegin": Timestamp("2011-03-01 09:00:00"),
"BQuarterBegin": Timestamp("2011-03-01 09:00:00"),
"QuarterEnd": Timestamp("2011-03-31 09:00:00"),
"BQuarterEnd": Timestamp("2011-03-31 09:00:00"),
"BusinessHour": Timestamp("2011-01-03 10:00:00"),
"CustomBusinessHour": Timestamp("2011-01-03 10:00:00"),
"WeekOfMonth": Timestamp("2011-01-08 09:00:00"),
"LastWeekOfMonth": Timestamp("2011-01-29 09:00:00"),
"FY5253Quarter": Timestamp("2011-01-25 09:00:00"),
"FY5253": Timestamp("2011-01-25 09:00:00"),
"Week": Timestamp("2011-01-08 09:00:00"),
"Easter": Timestamp("2011-04-24 09:00:00"),
"Hour": Timestamp("2011-01-01 10:00:00"),
"Minute": Timestamp("2011-01-01 09:01:00"),
"Second": Timestamp("2011-01-01 09:00:01"),
"Milli": Timestamp("2011-01-01 09:00:00.001000"),
"Micro": Timestamp("2011-01-01 09:00:00.000001"),
"Nano": Timestamp("2011-01-01T09:00:00.000000001"),
}
def test_immutable(self, offset_types):
# GH#21341 check that __setattr__ raises
offset = self._get_offset(offset_types)
msg = "objects is not writable|DateOffset objects are immutable"
with pytest.raises(AttributeError, match=msg):
offset.normalize = True
with pytest.raises(AttributeError, match=msg):
offset.n = 91
def test_return_type(self, offset_types):
offset = self._get_offset(offset_types)
# make sure that we are returning a Timestamp
result = Timestamp("20080101") + offset
assert isinstance(result, Timestamp)
# make sure that we are returning NaT
assert NaT + offset is NaT
assert offset + NaT is NaT
assert NaT - offset is NaT
assert (-offset)._apply(NaT) is NaT
def test_offset_n(self, offset_types):
offset = self._get_offset(offset_types)
assert offset.n == 1
neg_offset = offset * -1
assert neg_offset.n == -1
mul_offset = offset * 3
assert mul_offset.n == 3
def test_offset_timedelta64_arg(self, offset_types):
# check that offset._validate_n raises TypeError on a timedelt64
# object
off = self._get_offset(offset_types)
td64 = np.timedelta64(4567, "s")
with pytest.raises(TypeError, match="argument must be an integer"):
type(off)(n=td64, **off.kwds)
def test_offset_mul_ndarray(self, offset_types):
off = self._get_offset(offset_types)
expected = np.array([[off, off * 2], [off * 3, off * 4]])
result = np.array([[1, 2], [3, 4]]) * off
tm.assert_numpy_array_equal(result, expected)
result = off * np.array([[1, 2], [3, 4]])
tm.assert_numpy_array_equal(result, expected)
def test_offset_freqstr(self, offset_types):
offset = self._get_offset(offset_types)
freqstr = offset.freqstr
if freqstr not in ("<Easter>", "<DateOffset: days=1>", "LWOM-SAT"):
code = _get_offset(freqstr)
assert offset.rule_code == code
def _check_offsetfunc_works(self, offset, funcname, dt, expected, normalize=False):
if normalize and issubclass(offset, Tick):
# normalize=True disallowed for Tick subclasses GH#21427
return
offset_s = self._get_offset(offset, normalize=normalize)
func = getattr(offset_s, funcname)
result = func(dt)
assert isinstance(result, Timestamp)
assert result == expected
result = func(Timestamp(dt))
assert isinstance(result, Timestamp)
assert result == expected
# see gh-14101
exp_warning = None
ts = Timestamp(dt) + Nano(5)
if (
type(offset_s).__name__ == "DateOffset"
and (funcname in ["apply", "_apply"] or normalize)
and ts.nanosecond > 0
):
exp_warning = UserWarning
# test nanosecond is preserved
with tm.assert_produces_warning(exp_warning):
result = func(ts)
if exp_warning is None and funcname == "_apply":
# GH#44522
# Check in this particular case to avoid headaches with
# testing for multiple warnings produced by the same call.
with tm.assert_produces_warning(FutureWarning, match="apply is deprecated"):
res2 = offset_s.apply(ts)
assert type(res2) is type(result)
assert res2 == result
assert isinstance(result, Timestamp)
if normalize is False:
assert result == expected + Nano(5)
else:
assert result == expected
if isinstance(dt, np.datetime64):
# test tz when input is datetime or Timestamp
return
for tz in self.timezones:
expected_localize = expected.tz_localize(tz)
tz_obj = timezones.maybe_get_tz(tz)
dt_tz = conversion.localize_pydatetime(dt, tz_obj)
result = func(dt_tz)
assert isinstance(result, Timestamp)
assert result == expected_localize
result = func(Timestamp(dt, tz=tz))
assert isinstance(result, Timestamp)
assert result == expected_localize
# see gh-14101
exp_warning = None
ts = Timestamp(dt, tz=tz) + Nano(5)
if (
type(offset_s).__name__ == "DateOffset"
and (funcname in ["apply", "_apply"] or normalize)
and ts.nanosecond > 0
):
exp_warning = UserWarning
# test nanosecond is preserved
with tm.assert_produces_warning(exp_warning):
result = func(ts)
assert isinstance(result, Timestamp)
if normalize is False:
assert result == expected_localize + Nano(5)
else:
assert result == expected_localize
def test_apply(self, offset_types):
sdt = datetime(2011, 1, 1, 9, 0)
ndt = np.datetime64("2011-01-01 09:00")
expected = self.expecteds[offset_types.__name__]
expected_norm = Timestamp(expected.date())
for dt in [sdt, ndt]:
self._check_offsetfunc_works(offset_types, "_apply", dt, expected)
self._check_offsetfunc_works(
offset_types, "_apply", dt, expected_norm, normalize=True
)
def test_rollforward(self, offset_types):
expecteds = self.expecteds.copy()
# result will not be changed if the target is on the offset
no_changes = [
"Day",
"MonthBegin",
"SemiMonthBegin",
"YearBegin",
"Week",
"Hour",
"Minute",
"Second",
"Milli",
"Micro",
"Nano",
"DateOffset",
]
for n in no_changes:
expecteds[n] = Timestamp("2011/01/01 09:00")
expecteds["BusinessHour"] = Timestamp("2011-01-03 09:00:00")
expecteds["CustomBusinessHour"] = Timestamp("2011-01-03 09:00:00")
# but be changed when normalize=True
norm_expected = expecteds.copy()
for k in norm_expected:
norm_expected[k] = Timestamp(norm_expected[k].date())
normalized = {
"Day": Timestamp("2011-01-02 00:00:00"),
"DateOffset": Timestamp("2011-01-02 00:00:00"),
"MonthBegin": Timestamp("2011-02-01 00:00:00"),
"SemiMonthBegin": Timestamp("2011-01-15 00:00:00"),
"YearBegin": Timestamp("2012-01-01 00:00:00"),
"Week": Timestamp("2011-01-08 00:00:00"),
"Hour": Timestamp("2011-01-01 00:00:00"),
"Minute": Timestamp("2011-01-01 00:00:00"),
"Second": Timestamp("2011-01-01 00:00:00"),
"Milli": Timestamp("2011-01-01 00:00:00"),
"Micro": Timestamp("2011-01-01 00:00:00"),
}
norm_expected.update(normalized)
sdt = datetime(2011, 1, 1, 9, 0)
ndt = np.datetime64("2011-01-01 09:00")
for dt in [sdt, ndt]:
expected = expecteds[offset_types.__name__]
self._check_offsetfunc_works(offset_types, "rollforward", dt, expected)
expected = norm_expected[offset_types.__name__]
self._check_offsetfunc_works(
offset_types, "rollforward", dt, expected, normalize=True
)
def test_rollback(self, offset_types):
expecteds = {
"BusinessDay": Timestamp("2010-12-31 09:00:00"),
"CustomBusinessDay": Timestamp("2010-12-31 09:00:00"),
"CustomBusinessMonthEnd": Timestamp("2010-12-31 09:00:00"),
"CustomBusinessMonthBegin": Timestamp("2010-12-01 09:00:00"),
"BusinessMonthBegin": Timestamp("2010-12-01 09:00:00"),
"MonthEnd": Timestamp("2010-12-31 09:00:00"),
"SemiMonthEnd": Timestamp("2010-12-31 09:00:00"),
"BusinessMonthEnd": Timestamp("2010-12-31 09:00:00"),
"BYearBegin": Timestamp("2010-01-01 09:00:00"),
"YearEnd": Timestamp("2010-12-31 09:00:00"),
"BYearEnd": Timestamp("2010-12-31 09:00:00"),
"QuarterBegin": Timestamp("2010-12-01 09:00:00"),
"BQuarterBegin": Timestamp("2010-12-01 09:00:00"),
"QuarterEnd": Timestamp("2010-12-31 09:00:00"),
"BQuarterEnd": Timestamp("2010-12-31 09:00:00"),
"BusinessHour": Timestamp("2010-12-31 17:00:00"),
"CustomBusinessHour": Timestamp("2010-12-31 17:00:00"),
"WeekOfMonth": Timestamp("2010-12-11 09:00:00"),
"LastWeekOfMonth": Timestamp("2010-12-25 09:00:00"),
"FY5253Quarter": Timestamp("2010-10-26 09:00:00"),
"FY5253": Timestamp("2010-01-26 09:00:00"),
"Easter": Timestamp("2010-04-04 09:00:00"),
}
# result will not be changed if the target is on the offset
for n in [
"Day",
"MonthBegin",
"SemiMonthBegin",
"YearBegin",
"Week",
"Hour",
"Minute",
"Second",
"Milli",
"Micro",
"Nano",
"DateOffset",
]:
expecteds[n] = Timestamp("2011/01/01 09:00")
# but be changed when normalize=True
norm_expected = expecteds.copy()
for k in norm_expected:
norm_expected[k] = Timestamp(norm_expected[k].date())
normalized = {
"Day": Timestamp("2010-12-31 00:00:00"),
"DateOffset": Timestamp("2010-12-31 00:00:00"),
"MonthBegin": Timestamp("2010-12-01 00:00:00"),
"SemiMonthBegin": Timestamp("2010-12-15 00:00:00"),
"YearBegin": Timestamp("2010-01-01 00:00:00"),
"Week": Timestamp("2010-12-25 00:00:00"),
"Hour": Timestamp("2011-01-01 00:00:00"),
"Minute": Timestamp("2011-01-01 00:00:00"),
"Second": Timestamp("2011-01-01 00:00:00"),
"Milli": Timestamp("2011-01-01 00:00:00"),
"Micro": Timestamp("2011-01-01 00:00:00"),
}
norm_expected.update(normalized)
sdt = datetime(2011, 1, 1, 9, 0)
ndt = np.datetime64("2011-01-01 09:00")
for dt in [sdt, ndt]:
expected = expecteds[offset_types.__name__]
self._check_offsetfunc_works(offset_types, "rollback", dt, expected)
expected = norm_expected[offset_types.__name__]
self._check_offsetfunc_works(
offset_types, "rollback", dt, expected, normalize=True
)
def test_is_on_offset(self, offset_types):
dt = self.expecteds[offset_types.__name__]
offset_s = self._get_offset(offset_types)
assert offset_s.is_on_offset(dt)
# when normalize=True, is_on_offset checks time is 00:00:00
if issubclass(offset_types, Tick):
# normalize=True disallowed for Tick subclasses GH#21427
return
offset_n = self._get_offset(offset_types, normalize=True)
assert not offset_n.is_on_offset(dt)
if offset_types in (BusinessHour, CustomBusinessHour):
# In default BusinessHour (9:00-17:00), normalized time
# cannot be in business hour range
return
date = datetime(dt.year, dt.month, dt.day)
assert offset_n.is_on_offset(date)
def test_add(self, offset_types, tz_naive_fixture):
tz = tz_naive_fixture
dt = datetime(2011, 1, 1, 9, 0)
offset_s = self._get_offset(offset_types)
expected = self.expecteds[offset_types.__name__]
result_dt = dt + offset_s
result_ts = Timestamp(dt) + offset_s
for result in [result_dt, result_ts]:
assert isinstance(result, Timestamp)
assert result == expected
expected_localize = expected.tz_localize(tz)
result = Timestamp(dt, tz=tz) + offset_s
assert isinstance(result, Timestamp)
assert result == expected_localize
# normalize=True, disallowed for Tick subclasses GH#21427
if issubclass(offset_types, Tick):
return
offset_s = self._get_offset(offset_types, normalize=True)
expected = Timestamp(expected.date())
result_dt = dt + offset_s
result_ts = Timestamp(dt) + offset_s
for result in [result_dt, result_ts]:
assert isinstance(result, Timestamp)
assert result == expected
expected_localize = expected.tz_localize(tz)
result = Timestamp(dt, tz=tz) + offset_s
assert isinstance(result, Timestamp)
assert result == expected_localize
def test_add_empty_datetimeindex(self, offset_types, tz_naive_fixture):
# GH#12724, GH#30336
offset_s = self._get_offset(offset_types)
dti = DatetimeIndex([], tz=tz_naive_fixture)
warn = None
if isinstance(
offset_s,
(
Easter,
WeekOfMonth,
LastWeekOfMonth,
CustomBusinessDay,
BusinessHour,
CustomBusinessHour,
CustomBusinessMonthBegin,
CustomBusinessMonthEnd,
FY5253,
FY5253Quarter,
),
):
# We don't have an optimized apply_index
warn = PerformanceWarning
with tm.assert_produces_warning(warn):
result = dti + offset_s
tm.assert_index_equal(result, dti)
with tm.assert_produces_warning(warn):
result = offset_s + dti
tm.assert_index_equal(result, dti)
dta = dti._data
with tm.assert_produces_warning(warn):
result = dta + offset_s
tm.assert_equal(result, dta)
with tm.assert_produces_warning(warn):
result = offset_s + dta
tm.assert_equal(result, dta)
def test_pickle_roundtrip(self, offset_types):
off = self._get_offset(offset_types)
res = tm.round_trip_pickle(off)
assert off == res
if type(off) is not DateOffset:
for attr in off._attributes:
if attr == "calendar":
# np.busdaycalendar __eq__ will return False;
# we check holidays and weekmask attrs so are OK
continue
# Make sure nothings got lost from _params (which __eq__) is based on
assert getattr(off, attr) == getattr(res, attr)
def test_pickle_dateoffset_odd_inputs(self):
# GH#34511
off = DateOffset(months=12)
res = tm.round_trip_pickle(off)
assert off == res
base_dt = datetime(2020, 1, 1)
assert base_dt + off == base_dt + res
def test_onOffset_deprecated(self, offset_types, fixed_now_ts):
# GH#30340 use idiomatic naming
off = self._get_offset(offset_types)
ts = fixed_now_ts
with tm.assert_produces_warning(FutureWarning):
result = off.onOffset(ts)
expected = off.is_on_offset(ts)
assert result == expected
def test_isAnchored_deprecated(self, offset_types):
# GH#30340 use idiomatic naming
off = self._get_offset(offset_types)
with tm.assert_produces_warning(FutureWarning):
result = off.isAnchored()
expected = off.is_anchored()
assert result == expected
def test_offsets_hashable(self, offset_types):
# GH: 37267
off = self._get_offset(offset_types)
assert hash(off) is not None
class TestDateOffset(Base):
def setup_method(self, method):
self.d = Timestamp(datetime(2008, 1, 2))
_offset_map.clear()
def test_repr(self):
repr(DateOffset())
repr(DateOffset(2))
repr(2 * DateOffset())
repr(2 * DateOffset(months=2))
def test_mul(self):
assert DateOffset(2) == 2 * DateOffset(1)
assert DateOffset(2) == DateOffset(1) * 2
def test_constructor(self):
assert (self.d + DateOffset(months=2)) == datetime(2008, 3, 2)
assert (self.d - DateOffset(months=2)) == datetime(2007, 11, 2)
assert (self.d + DateOffset(2)) == datetime(2008, 1, 4)
assert not DateOffset(2).is_anchored()
assert DateOffset(1).is_anchored()
d = datetime(2008, 1, 31)
assert (d + DateOffset(months=1)) == datetime(2008, 2, 29)
def test_copy(self):
assert DateOffset(months=2).copy() == DateOffset(months=2)
def test_eq(self):
offset1 = DateOffset(days=1)
offset2 = DateOffset(days=365)
assert offset1 != offset2
class TestOffsetNames:
def test_get_offset_name(self):
assert BDay().freqstr == "B"
assert BDay(2).freqstr == "2B"
assert BMonthEnd().freqstr == "BM"
assert Week(weekday=0).freqstr == "W-MON"
assert Week(weekday=1).freqstr == "W-TUE"
assert Week(weekday=2).freqstr == "W-WED"
assert Week(weekday=3).freqstr == "W-THU"
assert Week(weekday=4).freqstr == "W-FRI"
assert LastWeekOfMonth(weekday=WeekDay.SUN).freqstr == "LWOM-SUN"
def test_get_offset():
with pytest.raises(ValueError, match=INVALID_FREQ_ERR_MSG):
_get_offset("gibberish")
with pytest.raises(ValueError, match=INVALID_FREQ_ERR_MSG):
_get_offset("QS-JAN-B")
pairs = [
("B", BDay()),
("b", BDay()),
("bm", BMonthEnd()),
("Bm", BMonthEnd()),
("W-MON", Week(weekday=0)),
("W-TUE", Week(weekday=1)),
("W-WED", Week(weekday=2)),
("W-THU", Week(weekday=3)),
("W-FRI", Week(weekday=4)),
]
for name, expected in pairs:
offset = _get_offset(name)
assert offset == expected, (
f"Expected {repr(name)} to yield {repr(expected)} "
f"(actual: {repr(offset)})"
)
def test_get_offset_legacy():
pairs = [("w@Sat", Week(weekday=5))]
for name, expected in pairs:
with pytest.raises(ValueError, match=INVALID_FREQ_ERR_MSG):
_get_offset(name)
class TestOffsetAliases:
def setup_method(self, method):
_offset_map.clear()
def test_alias_equality(self):
for k, v in _offset_map.items():
if v is None:
continue
assert k == v.copy()
def test_rule_code(self):
lst = ["M", "MS", "BM", "BMS", "D", "B", "H", "T", "S", "L", "U"]
for k in lst:
assert k == _get_offset(k).rule_code
# should be cached - this is kind of an internals test...
assert k in _offset_map
assert k == (_get_offset(k) * 3).rule_code
suffix_lst = ["MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"]
base = "W"
for v in suffix_lst:
alias = "-".join([base, v])
assert alias == _get_offset(alias).rule_code
assert alias == (_get_offset(alias) * 5).rule_code
suffix_lst = [
"JAN",
"FEB",
"MAR",
"APR",
"MAY",
"JUN",
"JUL",
"AUG",
"SEP",
"OCT",
"NOV",
"DEC",
]
base_lst = ["A", "AS", "BA", "BAS", "Q", "QS", "BQ", "BQS"]
for base in base_lst:
for v in suffix_lst:
alias = "-".join([base, v])
assert alias == _get_offset(alias).rule_code
assert alias == (_get_offset(alias) * 5).rule_code
def test_freq_offsets():
off = BDay(1, offset=timedelta(0, 1800))
assert off.freqstr == "B+30Min"
off = BDay(1, offset=timedelta(0, -1800))
assert off.freqstr == "B-30Min"
class TestReprNames:
def test_str_for_named_is_name(self):
# look at all the amazing combinations!
month_prefixes = ["A", "AS", "BA", "BAS", "Q", "BQ", "BQS", "QS"]
names = [
prefix + "-" + month
for prefix in month_prefixes
for month in [
"JAN",
"FEB",
"MAR",
"APR",
"MAY",
"JUN",
"JUL",
"AUG",
"SEP",
"OCT",
"NOV",
"DEC",
]
]
days = ["MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"]
names += ["W-" + day for day in days]
names += ["WOM-" + week + day for week in ("1", "2", "3", "4") for day in days]
_offset_map.clear()
for name in names:
offset = _get_offset(name)
assert offset.freqstr == name
def get_utc_offset_hours(ts):
# take a Timestamp and compute total hours of utc offset
o = ts.utcoffset()
return (o.days * 24 * 3600 + o.seconds) / 3600.0
# ---------------------------------------------------------------------
def test_valid_default_arguments(offset_types):
# GH#19142 check that the calling the constructors without passing
# any keyword arguments produce valid offsets
cls = offset_types
cls()
@pytest.mark.parametrize("kwd", sorted(liboffsets._relativedelta_kwds))
def test_valid_month_attributes(kwd, month_classes):
# GH#18226
cls = month_classes
# check that we cannot create e.g. MonthEnd(weeks=3)
msg = rf"__init__\(\) got an unexpected keyword argument '{kwd}'"
with pytest.raises(TypeError, match=msg):
cls(**{kwd: 3})
def test_month_offset_name(month_classes):
# GH#33757 off.name with n != 1 should not raise AttributeError
obj = month_classes(1)
obj2 = month_classes(2)
assert obj2.name == obj.name
@pytest.mark.parametrize("kwd", sorted(liboffsets._relativedelta_kwds))
def test_valid_relativedelta_kwargs(kwd):
# Check that all the arguments specified in liboffsets._relativedelta_kwds
# are in fact valid relativedelta keyword args
DateOffset(**{kwd: 1})
@pytest.mark.parametrize("kwd", sorted(liboffsets._relativedelta_kwds))
def test_valid_tick_attributes(kwd, tick_classes):
# GH#18226
cls = tick_classes
# check that we cannot create e.g. Hour(weeks=3)
msg = rf"__init__\(\) got an unexpected keyword argument '{kwd}'"
with pytest.raises(TypeError, match=msg):
cls(**{kwd: 3})
def test_validate_n_error():
with pytest.raises(TypeError, match="argument must be an integer"):
DateOffset(n="Doh!")
with pytest.raises(TypeError, match="argument must be an integer"):
MonthBegin(n=timedelta(1))
with pytest.raises(TypeError, match="argument must be an integer"):
BDay(n=np.array([1, 2], dtype=np.int64))
def test_require_integers(offset_types):
cls = offset_types
with pytest.raises(ValueError, match="argument must be an integer"):
cls(n=1.5)
def test_tick_normalize_raises(tick_classes):
# check that trying to create a Tick object with normalize=True raises
# GH#21427
cls = tick_classes
msg = "Tick offset with `normalize=True` are not allowed."
with pytest.raises(ValueError, match=msg):
cls(n=3, normalize=True)
@pytest.mark.parametrize(
"offset_kwargs, expected_arg",
[
({"nanoseconds": 1}, "1970-01-01 00:00:00.000000001"),
({"nanoseconds": 5}, "1970-01-01 00:00:00.000000005"),
({"nanoseconds": -1}, "1969-12-31 23:59:59.999999999"),
({"microseconds": 1}, "1970-01-01 00:00:00.000001"),
({"microseconds": -1}, "1969-12-31 23:59:59.999999"),
({"seconds": 1}, "1970-01-01 00:00:01"),
({"seconds": -1}, "1969-12-31 23:59:59"),
({"minutes": 1}, "1970-01-01 00:01:00"),
({"minutes": -1}, "1969-12-31 23:59:00"),
({"hours": 1}, "1970-01-01 01:00:00"),
({"hours": -1}, "1969-12-31 23:00:00"),
({"days": 1}, "1970-01-02 00:00:00"),
({"days": -1}, "1969-12-31 00:00:00"),
({"weeks": 1}, "1970-01-08 00:00:00"),
({"weeks": -1}, "1969-12-25 00:00:00"),
({"months": 1}, "1970-02-01 00:00:00"),
({"months": -1}, "1969-12-01 00:00:00"),
({"years": 1}, "1971-01-01 00:00:00"),
({"years": -1}, "1969-01-01 00:00:00"),
],
)
def test_dateoffset_add_sub(offset_kwargs, expected_arg):
offset = DateOffset(**offset_kwargs)
ts = Timestamp(0)
result = ts + offset
expected = Timestamp(expected_arg)
assert result == expected
result -= offset
assert result == ts
result = offset + ts
assert result == expected
def test_dataoffset_add_sub_timestamp_with_nano():
offset = DateOffset(minutes=2, nanoseconds=9)
ts = Timestamp(4)
result = ts + offset
expected = Timestamp("1970-01-01 00:02:00.000000013")
assert result == expected
result -= offset
assert result == ts
result = offset + ts
assert result == expected
@pytest.mark.parametrize(
"attribute",
[
"hours",
"days",
"weeks",
"months",
"years",
],
)
def test_dateoffset_immutable(attribute):
offset = DateOffset(**{attribute: 0})
msg = "DateOffset objects are immutable"
with pytest.raises(AttributeError, match=msg):
setattr(offset, attribute, 5)
def test_dateoffset_misc():
oset = offsets.DateOffset(months=2, days=4)
# it works
oset.freqstr
assert not offsets.DateOffset(months=2) == 2
@pytest.mark.parametrize("n", [-1, 1, 3])
def test_construct_int_arg_no_kwargs_assumed_days(n):
# GH 45890, 45643
offset = DateOffset(n)
assert offset._offset == timedelta(1)
result = Timestamp(2022, 1, 2) + offset
expected = Timestamp(2022, 1, 2 + n)
assert result == expected