done
This commit is contained in:
		| @ -0,0 +1,37 @@ | ||||
| """ | ||||
| Assertion helpers and base class for offsets tests | ||||
| """ | ||||
| from __future__ import annotations | ||||
|  | ||||
|  | ||||
| def assert_offset_equal(offset, base, expected): | ||||
|     actual = offset + base | ||||
|     actual_swapped = base + offset | ||||
|     actual_apply = offset._apply(base) | ||||
|     try: | ||||
|         assert actual == expected | ||||
|         assert actual_swapped == expected | ||||
|         assert actual_apply == expected | ||||
|     except AssertionError as err: | ||||
|         raise AssertionError( | ||||
|             f"\nExpected: {expected}\nActual: {actual}\nFor Offset: {offset})" | ||||
|             f"\nAt Date: {base}" | ||||
|         ) from err | ||||
|  | ||||
|  | ||||
| def assert_is_on_offset(offset, date, expected): | ||||
|     actual = offset.is_on_offset(date) | ||||
|     assert actual == expected, ( | ||||
|         f"\nExpected: {expected}\nActual: {actual}\nFor Offset: {offset})" | ||||
|         f"\nAt Date: {date}" | ||||
|     ) | ||||
|  | ||||
|  | ||||
| class WeekDay: | ||||
|     MON = 0 | ||||
|     TUE = 1 | ||||
|     WED = 2 | ||||
|     THU = 3 | ||||
|     FRI = 4 | ||||
|     SAT = 5 | ||||
|     SUN = 6 | ||||
| @ -0,0 +1,236 @@ | ||||
| """ | ||||
| Tests for offsets.BDay | ||||
| """ | ||||
| from __future__ import annotations | ||||
|  | ||||
| from datetime import ( | ||||
|     date, | ||||
|     datetime, | ||||
|     timedelta, | ||||
| ) | ||||
|  | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas._libs.tslibs.offsets import ( | ||||
|     ApplyTypeError, | ||||
|     BDay, | ||||
|     BMonthEnd, | ||||
| ) | ||||
|  | ||||
| from pandas import ( | ||||
|     DatetimeIndex, | ||||
|     Timedelta, | ||||
|     _testing as tm, | ||||
| ) | ||||
| from pandas.tests.tseries.offsets.common import ( | ||||
|     assert_is_on_offset, | ||||
|     assert_offset_equal, | ||||
| ) | ||||
|  | ||||
| from pandas.tseries import offsets | ||||
|  | ||||
|  | ||||
| @pytest.fixture | ||||
| def dt(): | ||||
|     return datetime(2008, 1, 1) | ||||
|  | ||||
|  | ||||
| @pytest.fixture | ||||
| def _offset(): | ||||
|     return BDay | ||||
|  | ||||
|  | ||||
| @pytest.fixture | ||||
| def offset(_offset): | ||||
|     return _offset() | ||||
|  | ||||
|  | ||||
| @pytest.fixture | ||||
| def offset2(_offset): | ||||
|     return _offset(2) | ||||
|  | ||||
|  | ||||
| class TestBusinessDay: | ||||
|     def test_different_normalize_equals(self, _offset, offset2): | ||||
|         # GH#21404 changed __eq__ to return False when `normalize` does not match | ||||
|         offset = _offset() | ||||
|         offset2 = _offset(normalize=True) | ||||
|         assert offset != offset2 | ||||
|  | ||||
|     def test_repr(self, offset, offset2): | ||||
|         assert repr(offset) == "<BusinessDay>" | ||||
|         assert repr(offset2) == "<2 * BusinessDays>" | ||||
|  | ||||
|         expected = "<BusinessDay: offset=datetime.timedelta(days=1)>" | ||||
|         assert repr(offset + timedelta(1)) == expected | ||||
|  | ||||
|     def test_with_offset(self, dt, offset): | ||||
|         offset = offset + timedelta(hours=2) | ||||
|  | ||||
|         assert (dt + offset) == datetime(2008, 1, 2, 2) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "td", | ||||
|         [ | ||||
|             Timedelta(hours=2), | ||||
|             Timedelta(hours=2).to_pytimedelta(), | ||||
|             Timedelta(hours=2).to_timedelta64(), | ||||
|         ], | ||||
|         ids=lambda x: type(x), | ||||
|     ) | ||||
|     def test_with_offset_index(self, td, dt, offset): | ||||
|         dti = DatetimeIndex([dt]) | ||||
|         expected = DatetimeIndex([datetime(2008, 1, 2, 2)]) | ||||
|  | ||||
|         result = dti + (td + offset) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = dti + (offset + td) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_eq(self, offset2): | ||||
|         assert offset2 == offset2 | ||||
|  | ||||
|     def test_hash(self, offset2): | ||||
|         assert hash(offset2) == hash(offset2) | ||||
|  | ||||
|     def test_add_datetime(self, dt, offset2): | ||||
|         assert offset2 + dt == datetime(2008, 1, 3) | ||||
|         assert offset2 + np.datetime64("2008-01-01 00:00:00") == datetime(2008, 1, 3) | ||||
|  | ||||
|     def testRollback1(self, dt, _offset): | ||||
|         assert _offset(10).rollback(dt) == dt | ||||
|  | ||||
|     def testRollback2(self, _offset): | ||||
|         assert _offset(10).rollback(datetime(2008, 1, 5)) == datetime(2008, 1, 4) | ||||
|  | ||||
|     def testRollforward1(self, dt, _offset): | ||||
|         assert _offset(10).rollforward(dt) == dt | ||||
|  | ||||
|     def testRollforward2(self, _offset): | ||||
|         assert _offset(10).rollforward(datetime(2008, 1, 5)) == datetime(2008, 1, 7) | ||||
|  | ||||
|     def test_roll_date_object(self, offset): | ||||
|         dt = date(2012, 9, 15) | ||||
|  | ||||
|         result = offset.rollback(dt) | ||||
|         assert result == datetime(2012, 9, 14) | ||||
|  | ||||
|         result = offset.rollforward(dt) | ||||
|         assert result == datetime(2012, 9, 17) | ||||
|  | ||||
|         offset = offsets.Day() | ||||
|         result = offset.rollback(dt) | ||||
|         assert result == datetime(2012, 9, 15) | ||||
|  | ||||
|         result = offset.rollforward(dt) | ||||
|         assert result == datetime(2012, 9, 15) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "dt, expected", | ||||
|         [ | ||||
|             (datetime(2008, 1, 1), True), | ||||
|             (datetime(2008, 1, 5), False), | ||||
|         ], | ||||
|     ) | ||||
|     def test_is_on_offset(self, offset, dt, expected): | ||||
|         assert_is_on_offset(offset, dt, expected) | ||||
|  | ||||
|     apply_cases: list[tuple[int, dict[datetime, datetime]]] = [ | ||||
|         ( | ||||
|             1, | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 2), | ||||
|                 datetime(2008, 1, 4): datetime(2008, 1, 7), | ||||
|                 datetime(2008, 1, 5): datetime(2008, 1, 7), | ||||
|                 datetime(2008, 1, 6): datetime(2008, 1, 7), | ||||
|                 datetime(2008, 1, 7): datetime(2008, 1, 8), | ||||
|             }, | ||||
|         ), | ||||
|         ( | ||||
|             2, | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 3), | ||||
|                 datetime(2008, 1, 4): datetime(2008, 1, 8), | ||||
|                 datetime(2008, 1, 5): datetime(2008, 1, 8), | ||||
|                 datetime(2008, 1, 6): datetime(2008, 1, 8), | ||||
|                 datetime(2008, 1, 7): datetime(2008, 1, 9), | ||||
|             }, | ||||
|         ), | ||||
|         ( | ||||
|             -1, | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2007, 12, 31), | ||||
|                 datetime(2008, 1, 4): datetime(2008, 1, 3), | ||||
|                 datetime(2008, 1, 5): datetime(2008, 1, 4), | ||||
|                 datetime(2008, 1, 6): datetime(2008, 1, 4), | ||||
|                 datetime(2008, 1, 7): datetime(2008, 1, 4), | ||||
|                 datetime(2008, 1, 8): datetime(2008, 1, 7), | ||||
|             }, | ||||
|         ), | ||||
|         ( | ||||
|             -2, | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2007, 12, 28), | ||||
|                 datetime(2008, 1, 4): datetime(2008, 1, 2), | ||||
|                 datetime(2008, 1, 5): datetime(2008, 1, 3), | ||||
|                 datetime(2008, 1, 6): datetime(2008, 1, 3), | ||||
|                 datetime(2008, 1, 7): datetime(2008, 1, 3), | ||||
|                 datetime(2008, 1, 8): datetime(2008, 1, 4), | ||||
|                 datetime(2008, 1, 9): datetime(2008, 1, 7), | ||||
|             }, | ||||
|         ), | ||||
|         ( | ||||
|             0, | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 1), | ||||
|                 datetime(2008, 1, 4): datetime(2008, 1, 4), | ||||
|                 datetime(2008, 1, 5): datetime(2008, 1, 7), | ||||
|                 datetime(2008, 1, 6): datetime(2008, 1, 7), | ||||
|                 datetime(2008, 1, 7): datetime(2008, 1, 7), | ||||
|             }, | ||||
|         ), | ||||
|     ] | ||||
|  | ||||
|     @pytest.mark.parametrize("case", apply_cases) | ||||
|     def test_apply(self, case, _offset): | ||||
|         n, cases = case | ||||
|         offset = _offset(n) | ||||
|         for base, expected in cases.items(): | ||||
|             assert_offset_equal(offset, base, expected) | ||||
|  | ||||
|     def test_apply_large_n(self, _offset): | ||||
|         dt = datetime(2012, 10, 23) | ||||
|  | ||||
|         result = dt + _offset(10) | ||||
|         assert result == datetime(2012, 11, 6) | ||||
|  | ||||
|         result = dt + _offset(100) - _offset(100) | ||||
|         assert result == dt | ||||
|  | ||||
|         off = _offset() * 6 | ||||
|         rs = datetime(2012, 1, 1) - off | ||||
|         xp = datetime(2011, 12, 23) | ||||
|         assert rs == xp | ||||
|  | ||||
|         st = datetime(2011, 12, 18) | ||||
|         rs = st + off | ||||
|         xp = datetime(2011, 12, 26) | ||||
|         assert rs == xp | ||||
|  | ||||
|         off = _offset() * 10 | ||||
|         rs = datetime(2014, 1, 5) + off  # see #5890 | ||||
|         xp = datetime(2014, 1, 17) | ||||
|         assert rs == xp | ||||
|  | ||||
|     def test_apply_corner(self, _offset): | ||||
|         if _offset is BDay: | ||||
|             msg = "Only know how to combine business day with datetime or timedelta" | ||||
|         else: | ||||
|             msg = ( | ||||
|                 "Only know how to combine trading day " | ||||
|                 "with datetime, datetime64 or timedelta" | ||||
|             ) | ||||
|         with pytest.raises(ApplyTypeError, match=msg): | ||||
|             _offset()._apply(BMonthEnd()) | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -0,0 +1,217 @@ | ||||
| """ | ||||
| Tests for the following offsets: | ||||
| - BMonthBegin | ||||
| - BMonthEnd | ||||
| """ | ||||
| from __future__ import annotations | ||||
|  | ||||
| from datetime import datetime | ||||
|  | ||||
| import pytest | ||||
|  | ||||
| import pandas as pd | ||||
| from pandas.tests.tseries.offsets.common import ( | ||||
|     assert_is_on_offset, | ||||
|     assert_offset_equal, | ||||
| ) | ||||
|  | ||||
| from pandas.tseries.offsets import ( | ||||
|     BMonthBegin, | ||||
|     BMonthEnd, | ||||
| ) | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize("n", [-2, 1]) | ||||
| @pytest.mark.parametrize( | ||||
|     "cls", | ||||
|     [ | ||||
|         BMonthBegin, | ||||
|         BMonthEnd, | ||||
|     ], | ||||
| ) | ||||
| def test_apply_index(cls, n): | ||||
|     offset = cls(n=n) | ||||
|     rng = pd.date_range(start="1/1/2000", periods=100000, freq="min") | ||||
|     ser = pd.Series(rng) | ||||
|  | ||||
|     res = rng + offset | ||||
|     assert res.freq is None  # not retained | ||||
|     assert res[0] == rng[0] + offset | ||||
|     assert res[-1] == rng[-1] + offset | ||||
|     res2 = ser + offset | ||||
|     # apply_index is only for indexes, not series, so no res2_v2 | ||||
|     assert res2.iloc[0] == ser.iloc[0] + offset | ||||
|     assert res2.iloc[-1] == ser.iloc[-1] + offset | ||||
|  | ||||
|  | ||||
| class TestBMonthBegin: | ||||
|     def test_offsets_compare_equal(self): | ||||
|         # root cause of #456 | ||||
|         offset1 = BMonthBegin() | ||||
|         offset2 = BMonthBegin() | ||||
|         assert not offset1 != offset2 | ||||
|  | ||||
|     offset_cases = [] | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BMonthBegin(), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 2, 1), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 2, 1), | ||||
|                 datetime(2006, 12, 29): datetime(2007, 1, 1), | ||||
|                 datetime(2006, 12, 31): datetime(2007, 1, 1), | ||||
|                 datetime(2006, 9, 1): datetime(2006, 10, 2), | ||||
|                 datetime(2007, 1, 1): datetime(2007, 2, 1), | ||||
|                 datetime(2006, 12, 1): datetime(2007, 1, 1), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BMonthBegin(0), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 1), | ||||
|                 datetime(2006, 10, 2): datetime(2006, 10, 2), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 2, 1), | ||||
|                 datetime(2006, 12, 29): datetime(2007, 1, 1), | ||||
|                 datetime(2006, 12, 31): datetime(2007, 1, 1), | ||||
|                 datetime(2006, 9, 15): datetime(2006, 10, 2), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BMonthBegin(2), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 3, 3), | ||||
|                 datetime(2008, 1, 15): datetime(2008, 3, 3), | ||||
|                 datetime(2006, 12, 29): datetime(2007, 2, 1), | ||||
|                 datetime(2006, 12, 31): datetime(2007, 2, 1), | ||||
|                 datetime(2007, 1, 1): datetime(2007, 3, 1), | ||||
|                 datetime(2006, 11, 1): datetime(2007, 1, 1), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BMonthBegin(-1), | ||||
|             { | ||||
|                 datetime(2007, 1, 1): datetime(2006, 12, 1), | ||||
|                 datetime(2008, 6, 30): datetime(2008, 6, 2), | ||||
|                 datetime(2008, 6, 1): datetime(2008, 5, 1), | ||||
|                 datetime(2008, 3, 10): datetime(2008, 3, 3), | ||||
|                 datetime(2008, 12, 31): datetime(2008, 12, 1), | ||||
|                 datetime(2006, 12, 29): datetime(2006, 12, 1), | ||||
|                 datetime(2006, 12, 30): datetime(2006, 12, 1), | ||||
|                 datetime(2007, 1, 1): datetime(2006, 12, 1), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     @pytest.mark.parametrize("case", offset_cases) | ||||
|     def test_offset(self, case): | ||||
|         offset, cases = case | ||||
|         for base, expected in cases.items(): | ||||
|             assert_offset_equal(offset, base, expected) | ||||
|  | ||||
|     on_offset_cases = [ | ||||
|         (BMonthBegin(), datetime(2007, 12, 31), False), | ||||
|         (BMonthBegin(), datetime(2008, 1, 1), True), | ||||
|         (BMonthBegin(), datetime(2001, 4, 2), True), | ||||
|         (BMonthBegin(), datetime(2008, 3, 3), True), | ||||
|     ] | ||||
|  | ||||
|     @pytest.mark.parametrize("case", on_offset_cases) | ||||
|     def test_is_on_offset(self, case): | ||||
|         offset, dt, expected = case | ||||
|         assert_is_on_offset(offset, dt, expected) | ||||
|  | ||||
|  | ||||
| class TestBMonthEnd: | ||||
|     def test_normalize(self): | ||||
|         dt = datetime(2007, 1, 1, 3) | ||||
|  | ||||
|         result = dt + BMonthEnd(normalize=True) | ||||
|         expected = dt.replace(hour=0) + BMonthEnd() | ||||
|         assert result == expected | ||||
|  | ||||
|     def test_offsets_compare_equal(self): | ||||
|         # root cause of #456 | ||||
|         offset1 = BMonthEnd() | ||||
|         offset2 = BMonthEnd() | ||||
|         assert not offset1 != offset2 | ||||
|  | ||||
|     offset_cases = [] | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BMonthEnd(), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 31), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 2, 29), | ||||
|                 datetime(2006, 12, 29): datetime(2007, 1, 31), | ||||
|                 datetime(2006, 12, 31): datetime(2007, 1, 31), | ||||
|                 datetime(2007, 1, 1): datetime(2007, 1, 31), | ||||
|                 datetime(2006, 12, 1): datetime(2006, 12, 29), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BMonthEnd(0), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 31), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 1, 31), | ||||
|                 datetime(2006, 12, 29): datetime(2006, 12, 29), | ||||
|                 datetime(2006, 12, 31): datetime(2007, 1, 31), | ||||
|                 datetime(2007, 1, 1): datetime(2007, 1, 31), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BMonthEnd(2), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 2, 29), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 3, 31), | ||||
|                 datetime(2006, 12, 29): datetime(2007, 2, 28), | ||||
|                 datetime(2006, 12, 31): datetime(2007, 2, 28), | ||||
|                 datetime(2007, 1, 1): datetime(2007, 2, 28), | ||||
|                 datetime(2006, 11, 1): datetime(2006, 12, 29), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BMonthEnd(-1), | ||||
|             { | ||||
|                 datetime(2007, 1, 1): datetime(2006, 12, 29), | ||||
|                 datetime(2008, 6, 30): datetime(2008, 5, 30), | ||||
|                 datetime(2008, 12, 31): datetime(2008, 11, 28), | ||||
|                 datetime(2006, 12, 29): datetime(2006, 11, 30), | ||||
|                 datetime(2006, 12, 30): datetime(2006, 12, 29), | ||||
|                 datetime(2007, 1, 1): datetime(2006, 12, 29), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     @pytest.mark.parametrize("case", offset_cases) | ||||
|     def test_offset(self, case): | ||||
|         offset, cases = case | ||||
|         for base, expected in cases.items(): | ||||
|             assert_offset_equal(offset, base, expected) | ||||
|  | ||||
|     on_offset_cases = [ | ||||
|         (BMonthEnd(), datetime(2007, 12, 31), True), | ||||
|         (BMonthEnd(), datetime(2008, 1, 1), False), | ||||
|     ] | ||||
|  | ||||
|     @pytest.mark.parametrize("case", on_offset_cases) | ||||
|     def test_is_on_offset(self, case): | ||||
|         offset, dt, expected = case | ||||
|         assert_is_on_offset(offset, dt, expected) | ||||
| @ -0,0 +1,315 @@ | ||||
| """ | ||||
| Tests for the following offsets: | ||||
| - BQuarterBegin | ||||
| - BQuarterEnd | ||||
| """ | ||||
| from __future__ import annotations | ||||
|  | ||||
| from datetime import datetime | ||||
|  | ||||
| import pytest | ||||
|  | ||||
| import pandas._testing as tm | ||||
| from pandas.tests.tseries.offsets.common import ( | ||||
|     assert_is_on_offset, | ||||
|     assert_offset_equal, | ||||
| ) | ||||
|  | ||||
| from pandas.tseries.offsets import ( | ||||
|     BQuarterBegin, | ||||
|     BQuarterEnd, | ||||
| ) | ||||
|  | ||||
|  | ||||
| def test_quarterly_dont_normalize(): | ||||
|     date = datetime(2012, 3, 31, 5, 30) | ||||
|  | ||||
|     offsets = (BQuarterEnd, BQuarterBegin) | ||||
|  | ||||
|     for klass in offsets: | ||||
|         result = date + klass() | ||||
|         assert result.time() == date.time() | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize("offset", [BQuarterBegin(), BQuarterEnd()]) | ||||
| def test_on_offset(offset): | ||||
|     dates = [ | ||||
|         datetime(2016, m, d) | ||||
|         for m in [10, 11, 12] | ||||
|         for d in [1, 2, 3, 28, 29, 30, 31] | ||||
|         if not (m == 11 and d == 31) | ||||
|     ] | ||||
|     for date in dates: | ||||
|         res = offset.is_on_offset(date) | ||||
|         slow_version = date == (date + offset) - offset | ||||
|         assert res == slow_version | ||||
|  | ||||
|  | ||||
| class TestBQuarterBegin: | ||||
|     def test_repr(self): | ||||
|         expected = "<BusinessQuarterBegin: startingMonth=3>" | ||||
|         assert repr(BQuarterBegin()) == expected | ||||
|         expected = "<BusinessQuarterBegin: startingMonth=3>" | ||||
|         assert repr(BQuarterBegin(startingMonth=3)) == expected | ||||
|         expected = "<BusinessQuarterBegin: startingMonth=1>" | ||||
|         assert repr(BQuarterBegin(startingMonth=1)) == expected | ||||
|  | ||||
|     def test_is_anchored(self): | ||||
|         msg = "BQuarterBegin.is_anchored is deprecated " | ||||
|  | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             assert BQuarterBegin(startingMonth=1).is_anchored() | ||||
|             assert BQuarterBegin().is_anchored() | ||||
|             assert not BQuarterBegin(2, startingMonth=1).is_anchored() | ||||
|  | ||||
|     def test_offset_corner_case(self): | ||||
|         # corner | ||||
|         offset = BQuarterBegin(n=-1, startingMonth=1) | ||||
|         assert datetime(2007, 4, 3) + offset == datetime(2007, 4, 2) | ||||
|  | ||||
|     offset_cases = [] | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BQuarterBegin(startingMonth=1), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 4, 1), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 4, 1), | ||||
|                 datetime(2008, 2, 15): datetime(2008, 4, 1), | ||||
|                 datetime(2008, 2, 29): datetime(2008, 4, 1), | ||||
|                 datetime(2008, 3, 15): datetime(2008, 4, 1), | ||||
|                 datetime(2008, 3, 31): datetime(2008, 4, 1), | ||||
|                 datetime(2008, 4, 15): datetime(2008, 7, 1), | ||||
|                 datetime(2007, 3, 15): datetime(2007, 4, 2), | ||||
|                 datetime(2007, 2, 28): datetime(2007, 4, 2), | ||||
|                 datetime(2007, 1, 1): datetime(2007, 4, 2), | ||||
|                 datetime(2007, 4, 15): datetime(2007, 7, 2), | ||||
|                 datetime(2007, 7, 1): datetime(2007, 7, 2), | ||||
|                 datetime(2007, 4, 1): datetime(2007, 4, 2), | ||||
|                 datetime(2007, 4, 2): datetime(2007, 7, 2), | ||||
|                 datetime(2008, 4, 30): datetime(2008, 7, 1), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BQuarterBegin(startingMonth=2), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 2, 1), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 2, 1), | ||||
|                 datetime(2008, 1, 15): datetime(2008, 2, 1), | ||||
|                 datetime(2008, 2, 29): datetime(2008, 5, 1), | ||||
|                 datetime(2008, 3, 15): datetime(2008, 5, 1), | ||||
|                 datetime(2008, 3, 31): datetime(2008, 5, 1), | ||||
|                 datetime(2008, 4, 15): datetime(2008, 5, 1), | ||||
|                 datetime(2008, 8, 15): datetime(2008, 11, 3), | ||||
|                 datetime(2008, 9, 15): datetime(2008, 11, 3), | ||||
|                 datetime(2008, 11, 1): datetime(2008, 11, 3), | ||||
|                 datetime(2008, 4, 30): datetime(2008, 5, 1), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BQuarterBegin(startingMonth=1, n=0), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 1), | ||||
|                 datetime(2007, 12, 31): datetime(2008, 1, 1), | ||||
|                 datetime(2008, 2, 15): datetime(2008, 4, 1), | ||||
|                 datetime(2008, 2, 29): datetime(2008, 4, 1), | ||||
|                 datetime(2008, 1, 15): datetime(2008, 4, 1), | ||||
|                 datetime(2008, 2, 27): datetime(2008, 4, 1), | ||||
|                 datetime(2008, 3, 15): datetime(2008, 4, 1), | ||||
|                 datetime(2007, 4, 1): datetime(2007, 4, 2), | ||||
|                 datetime(2007, 4, 2): datetime(2007, 4, 2), | ||||
|                 datetime(2007, 7, 1): datetime(2007, 7, 2), | ||||
|                 datetime(2007, 4, 15): datetime(2007, 7, 2), | ||||
|                 datetime(2007, 7, 2): datetime(2007, 7, 2), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BQuarterBegin(startingMonth=1, n=-1), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2007, 10, 1), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 1, 1), | ||||
|                 datetime(2008, 2, 15): datetime(2008, 1, 1), | ||||
|                 datetime(2008, 2, 29): datetime(2008, 1, 1), | ||||
|                 datetime(2008, 3, 15): datetime(2008, 1, 1), | ||||
|                 datetime(2008, 3, 31): datetime(2008, 1, 1), | ||||
|                 datetime(2008, 4, 15): datetime(2008, 4, 1), | ||||
|                 datetime(2007, 7, 3): datetime(2007, 7, 2), | ||||
|                 datetime(2007, 4, 3): datetime(2007, 4, 2), | ||||
|                 datetime(2007, 7, 2): datetime(2007, 4, 2), | ||||
|                 datetime(2008, 4, 1): datetime(2008, 1, 1), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BQuarterBegin(startingMonth=1, n=2), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 7, 1), | ||||
|                 datetime(2008, 1, 15): datetime(2008, 7, 1), | ||||
|                 datetime(2008, 2, 29): datetime(2008, 7, 1), | ||||
|                 datetime(2008, 3, 15): datetime(2008, 7, 1), | ||||
|                 datetime(2007, 3, 31): datetime(2007, 7, 2), | ||||
|                 datetime(2007, 4, 15): datetime(2007, 10, 1), | ||||
|                 datetime(2008, 4, 30): datetime(2008, 10, 1), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     @pytest.mark.parametrize("case", offset_cases) | ||||
|     def test_offset(self, case): | ||||
|         offset, cases = case | ||||
|         for base, expected in cases.items(): | ||||
|             assert_offset_equal(offset, base, expected) | ||||
|  | ||||
|  | ||||
| class TestBQuarterEnd: | ||||
|     def test_repr(self): | ||||
|         expected = "<BusinessQuarterEnd: startingMonth=3>" | ||||
|         assert repr(BQuarterEnd()) == expected | ||||
|         expected = "<BusinessQuarterEnd: startingMonth=3>" | ||||
|         assert repr(BQuarterEnd(startingMonth=3)) == expected | ||||
|         expected = "<BusinessQuarterEnd: startingMonth=1>" | ||||
|         assert repr(BQuarterEnd(startingMonth=1)) == expected | ||||
|  | ||||
|     def test_is_anchored(self): | ||||
|         msg = "BQuarterEnd.is_anchored is deprecated " | ||||
|  | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             assert BQuarterEnd(startingMonth=1).is_anchored() | ||||
|             assert BQuarterEnd().is_anchored() | ||||
|             assert not BQuarterEnd(2, startingMonth=1).is_anchored() | ||||
|  | ||||
|     def test_offset_corner_case(self): | ||||
|         # corner | ||||
|         offset = BQuarterEnd(n=-1, startingMonth=1) | ||||
|         assert datetime(2010, 1, 31) + offset == datetime(2010, 1, 29) | ||||
|  | ||||
|     offset_cases = [] | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BQuarterEnd(startingMonth=1), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 31), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 4, 30), | ||||
|                 datetime(2008, 2, 15): datetime(2008, 4, 30), | ||||
|                 datetime(2008, 2, 29): datetime(2008, 4, 30), | ||||
|                 datetime(2008, 3, 15): datetime(2008, 4, 30), | ||||
|                 datetime(2008, 3, 31): datetime(2008, 4, 30), | ||||
|                 datetime(2008, 4, 15): datetime(2008, 4, 30), | ||||
|                 datetime(2008, 4, 30): datetime(2008, 7, 31), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BQuarterEnd(startingMonth=2), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 2, 29), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 2, 29), | ||||
|                 datetime(2008, 2, 15): datetime(2008, 2, 29), | ||||
|                 datetime(2008, 2, 29): datetime(2008, 5, 30), | ||||
|                 datetime(2008, 3, 15): datetime(2008, 5, 30), | ||||
|                 datetime(2008, 3, 31): datetime(2008, 5, 30), | ||||
|                 datetime(2008, 4, 15): datetime(2008, 5, 30), | ||||
|                 datetime(2008, 4, 30): datetime(2008, 5, 30), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BQuarterEnd(startingMonth=1, n=0), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 31), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 1, 31), | ||||
|                 datetime(2008, 2, 15): datetime(2008, 4, 30), | ||||
|                 datetime(2008, 2, 29): datetime(2008, 4, 30), | ||||
|                 datetime(2008, 3, 15): datetime(2008, 4, 30), | ||||
|                 datetime(2008, 3, 31): datetime(2008, 4, 30), | ||||
|                 datetime(2008, 4, 15): datetime(2008, 4, 30), | ||||
|                 datetime(2008, 4, 30): datetime(2008, 4, 30), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BQuarterEnd(startingMonth=1, n=-1), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2007, 10, 31), | ||||
|                 datetime(2008, 1, 31): datetime(2007, 10, 31), | ||||
|                 datetime(2008, 2, 15): datetime(2008, 1, 31), | ||||
|                 datetime(2008, 2, 29): datetime(2008, 1, 31), | ||||
|                 datetime(2008, 3, 15): datetime(2008, 1, 31), | ||||
|                 datetime(2008, 3, 31): datetime(2008, 1, 31), | ||||
|                 datetime(2008, 4, 15): datetime(2008, 1, 31), | ||||
|                 datetime(2008, 4, 30): datetime(2008, 1, 31), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BQuarterEnd(startingMonth=1, n=2), | ||||
|             { | ||||
|                 datetime(2008, 1, 31): datetime(2008, 7, 31), | ||||
|                 datetime(2008, 2, 15): datetime(2008, 7, 31), | ||||
|                 datetime(2008, 2, 29): datetime(2008, 7, 31), | ||||
|                 datetime(2008, 3, 15): datetime(2008, 7, 31), | ||||
|                 datetime(2008, 3, 31): datetime(2008, 7, 31), | ||||
|                 datetime(2008, 4, 15): datetime(2008, 7, 31), | ||||
|                 datetime(2008, 4, 30): datetime(2008, 10, 31), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     @pytest.mark.parametrize("case", offset_cases) | ||||
|     def test_offset(self, case): | ||||
|         offset, cases = case | ||||
|         for base, expected in cases.items(): | ||||
|             assert_offset_equal(offset, base, expected) | ||||
|  | ||||
|     on_offset_cases = [ | ||||
|         (BQuarterEnd(1, startingMonth=1), datetime(2008, 1, 31), True), | ||||
|         (BQuarterEnd(1, startingMonth=1), datetime(2007, 12, 31), False), | ||||
|         (BQuarterEnd(1, startingMonth=1), datetime(2008, 2, 29), False), | ||||
|         (BQuarterEnd(1, startingMonth=1), datetime(2007, 3, 30), False), | ||||
|         (BQuarterEnd(1, startingMonth=1), datetime(2007, 3, 31), False), | ||||
|         (BQuarterEnd(1, startingMonth=1), datetime(2008, 4, 30), True), | ||||
|         (BQuarterEnd(1, startingMonth=1), datetime(2008, 5, 30), False), | ||||
|         (BQuarterEnd(1, startingMonth=1), datetime(2007, 6, 29), False), | ||||
|         (BQuarterEnd(1, startingMonth=1), datetime(2007, 6, 30), False), | ||||
|         (BQuarterEnd(1, startingMonth=2), datetime(2008, 1, 31), False), | ||||
|         (BQuarterEnd(1, startingMonth=2), datetime(2007, 12, 31), False), | ||||
|         (BQuarterEnd(1, startingMonth=2), datetime(2008, 2, 29), True), | ||||
|         (BQuarterEnd(1, startingMonth=2), datetime(2007, 3, 30), False), | ||||
|         (BQuarterEnd(1, startingMonth=2), datetime(2007, 3, 31), False), | ||||
|         (BQuarterEnd(1, startingMonth=2), datetime(2008, 4, 30), False), | ||||
|         (BQuarterEnd(1, startingMonth=2), datetime(2008, 5, 30), True), | ||||
|         (BQuarterEnd(1, startingMonth=2), datetime(2007, 6, 29), False), | ||||
|         (BQuarterEnd(1, startingMonth=2), datetime(2007, 6, 30), False), | ||||
|         (BQuarterEnd(1, startingMonth=3), datetime(2008, 1, 31), False), | ||||
|         (BQuarterEnd(1, startingMonth=3), datetime(2007, 12, 31), True), | ||||
|         (BQuarterEnd(1, startingMonth=3), datetime(2008, 2, 29), False), | ||||
|         (BQuarterEnd(1, startingMonth=3), datetime(2007, 3, 30), True), | ||||
|         (BQuarterEnd(1, startingMonth=3), datetime(2007, 3, 31), False), | ||||
|         (BQuarterEnd(1, startingMonth=3), datetime(2008, 4, 30), False), | ||||
|         (BQuarterEnd(1, startingMonth=3), datetime(2008, 5, 30), False), | ||||
|         (BQuarterEnd(1, startingMonth=3), datetime(2007, 6, 29), True), | ||||
|         (BQuarterEnd(1, startingMonth=3), datetime(2007, 6, 30), False), | ||||
|     ] | ||||
|  | ||||
|     @pytest.mark.parametrize("case", on_offset_cases) | ||||
|     def test_is_on_offset(self, case): | ||||
|         offset, dt, expected = case | ||||
|         assert_is_on_offset(offset, dt, expected) | ||||
| @ -0,0 +1,215 @@ | ||||
| """ | ||||
| Tests for the following offsets: | ||||
| - BYearBegin | ||||
| - BYearEnd | ||||
| """ | ||||
| from __future__ import annotations | ||||
|  | ||||
| from datetime import datetime | ||||
|  | ||||
| import pytest | ||||
|  | ||||
| from pandas.tests.tseries.offsets.common import ( | ||||
|     assert_is_on_offset, | ||||
|     assert_offset_equal, | ||||
| ) | ||||
|  | ||||
| from pandas.tseries.offsets import ( | ||||
|     BYearBegin, | ||||
|     BYearEnd, | ||||
| ) | ||||
|  | ||||
|  | ||||
| class TestBYearBegin: | ||||
|     def test_misspecified(self): | ||||
|         msg = "Month must go from 1 to 12" | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             BYearBegin(month=13) | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             BYearEnd(month=13) | ||||
|  | ||||
|     offset_cases = [] | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BYearBegin(), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2009, 1, 1), | ||||
|                 datetime(2008, 6, 30): datetime(2009, 1, 1), | ||||
|                 datetime(2008, 12, 31): datetime(2009, 1, 1), | ||||
|                 datetime(2011, 1, 1): datetime(2011, 1, 3), | ||||
|                 datetime(2011, 1, 3): datetime(2012, 1, 2), | ||||
|                 datetime(2005, 12, 30): datetime(2006, 1, 2), | ||||
|                 datetime(2005, 12, 31): datetime(2006, 1, 2), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BYearBegin(0), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 1), | ||||
|                 datetime(2008, 6, 30): datetime(2009, 1, 1), | ||||
|                 datetime(2008, 12, 31): datetime(2009, 1, 1), | ||||
|                 datetime(2005, 12, 30): datetime(2006, 1, 2), | ||||
|                 datetime(2005, 12, 31): datetime(2006, 1, 2), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BYearBegin(-1), | ||||
|             { | ||||
|                 datetime(2007, 1, 1): datetime(2006, 1, 2), | ||||
|                 datetime(2009, 1, 4): datetime(2009, 1, 1), | ||||
|                 datetime(2009, 1, 1): datetime(2008, 1, 1), | ||||
|                 datetime(2008, 6, 30): datetime(2008, 1, 1), | ||||
|                 datetime(2008, 12, 31): datetime(2008, 1, 1), | ||||
|                 datetime(2006, 12, 29): datetime(2006, 1, 2), | ||||
|                 datetime(2006, 12, 30): datetime(2006, 1, 2), | ||||
|                 datetime(2006, 1, 1): datetime(2005, 1, 3), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BYearBegin(-2), | ||||
|             { | ||||
|                 datetime(2007, 1, 1): datetime(2005, 1, 3), | ||||
|                 datetime(2007, 6, 30): datetime(2006, 1, 2), | ||||
|                 datetime(2008, 12, 31): datetime(2007, 1, 1), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     @pytest.mark.parametrize("case", offset_cases) | ||||
|     def test_offset(self, case): | ||||
|         offset, cases = case | ||||
|         for base, expected in cases.items(): | ||||
|             assert_offset_equal(offset, base, expected) | ||||
|  | ||||
|  | ||||
| class TestBYearEnd: | ||||
|     offset_cases = [] | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BYearEnd(), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 12, 31), | ||||
|                 datetime(2008, 6, 30): datetime(2008, 12, 31), | ||||
|                 datetime(2008, 12, 31): datetime(2009, 12, 31), | ||||
|                 datetime(2005, 12, 30): datetime(2006, 12, 29), | ||||
|                 datetime(2005, 12, 31): datetime(2006, 12, 29), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BYearEnd(0), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 12, 31), | ||||
|                 datetime(2008, 6, 30): datetime(2008, 12, 31), | ||||
|                 datetime(2008, 12, 31): datetime(2008, 12, 31), | ||||
|                 datetime(2005, 12, 31): datetime(2006, 12, 29), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BYearEnd(-1), | ||||
|             { | ||||
|                 datetime(2007, 1, 1): datetime(2006, 12, 29), | ||||
|                 datetime(2008, 6, 30): datetime(2007, 12, 31), | ||||
|                 datetime(2008, 12, 31): datetime(2007, 12, 31), | ||||
|                 datetime(2006, 12, 29): datetime(2005, 12, 30), | ||||
|                 datetime(2006, 12, 30): datetime(2006, 12, 29), | ||||
|                 datetime(2007, 1, 1): datetime(2006, 12, 29), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BYearEnd(-2), | ||||
|             { | ||||
|                 datetime(2007, 1, 1): datetime(2005, 12, 30), | ||||
|                 datetime(2008, 6, 30): datetime(2006, 12, 29), | ||||
|                 datetime(2008, 12, 31): datetime(2006, 12, 29), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     @pytest.mark.parametrize("case", offset_cases) | ||||
|     def test_offset(self, case): | ||||
|         offset, cases = case | ||||
|         for base, expected in cases.items(): | ||||
|             assert_offset_equal(offset, base, expected) | ||||
|  | ||||
|     on_offset_cases = [ | ||||
|         (BYearEnd(), datetime(2007, 12, 31), True), | ||||
|         (BYearEnd(), datetime(2008, 1, 1), False), | ||||
|         (BYearEnd(), datetime(2006, 12, 31), False), | ||||
|         (BYearEnd(), datetime(2006, 12, 29), True), | ||||
|     ] | ||||
|  | ||||
|     @pytest.mark.parametrize("case", on_offset_cases) | ||||
|     def test_is_on_offset(self, case): | ||||
|         offset, dt, expected = case | ||||
|         assert_is_on_offset(offset, dt, expected) | ||||
|  | ||||
|  | ||||
| class TestBYearEndLagged: | ||||
|     def test_bad_month_fail(self): | ||||
|         msg = "Month must go from 1 to 12" | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             BYearEnd(month=13) | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             BYearEnd(month=0) | ||||
|  | ||||
|     offset_cases = [] | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BYearEnd(month=6), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 6, 30), | ||||
|                 datetime(2007, 6, 30): datetime(2008, 6, 30), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             BYearEnd(n=-1, month=6), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2007, 6, 29), | ||||
|                 datetime(2007, 6, 30): datetime(2007, 6, 29), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     @pytest.mark.parametrize("case", offset_cases) | ||||
|     def test_offset(self, case): | ||||
|         offset, cases = case | ||||
|         for base, expected in cases.items(): | ||||
|             assert_offset_equal(offset, base, expected) | ||||
|  | ||||
|     def test_roll(self): | ||||
|         offset = BYearEnd(month=6) | ||||
|         date = datetime(2009, 11, 30) | ||||
|  | ||||
|         assert offset.rollforward(date) == datetime(2010, 6, 30) | ||||
|         assert offset.rollback(date) == datetime(2009, 6, 30) | ||||
|  | ||||
|     on_offset_cases = [ | ||||
|         (BYearEnd(month=2), datetime(2007, 2, 28), True), | ||||
|         (BYearEnd(month=6), datetime(2007, 6, 30), False), | ||||
|     ] | ||||
|  | ||||
|     @pytest.mark.parametrize("case", on_offset_cases) | ||||
|     def test_is_on_offset(self, case): | ||||
|         offset, dt, expected = case | ||||
|         assert_is_on_offset(offset, dt, expected) | ||||
| @ -0,0 +1,268 @@ | ||||
| from datetime import datetime | ||||
|  | ||||
| from dateutil.tz.tz import tzlocal | ||||
| import pytest | ||||
|  | ||||
| from pandas._libs.tslibs import ( | ||||
|     OutOfBoundsDatetime, | ||||
|     Timestamp, | ||||
| ) | ||||
| from pandas.compat import ( | ||||
|     IS64, | ||||
|     is_platform_windows, | ||||
| ) | ||||
|  | ||||
| from pandas.tseries.offsets import ( | ||||
|     FY5253, | ||||
|     BDay, | ||||
|     BMonthBegin, | ||||
|     BMonthEnd, | ||||
|     BQuarterBegin, | ||||
|     BQuarterEnd, | ||||
|     BusinessHour, | ||||
|     BYearBegin, | ||||
|     BYearEnd, | ||||
|     CBMonthBegin, | ||||
|     CBMonthEnd, | ||||
|     CDay, | ||||
|     CustomBusinessHour, | ||||
|     DateOffset, | ||||
|     FY5253Quarter, | ||||
|     LastWeekOfMonth, | ||||
|     MonthBegin, | ||||
|     MonthEnd, | ||||
|     QuarterEnd, | ||||
|     SemiMonthBegin, | ||||
|     SemiMonthEnd, | ||||
|     Week, | ||||
|     WeekOfMonth, | ||||
|     YearBegin, | ||||
|     YearEnd, | ||||
| ) | ||||
|  | ||||
|  | ||||
| def _get_offset(klass, value=1, normalize=False): | ||||
|     # create instance from offset class | ||||
|     if klass is FY5253: | ||||
|         klass = klass( | ||||
|             n=value, | ||||
|             startingMonth=1, | ||||
|             weekday=1, | ||||
|             variation="last", | ||||
|             normalize=normalize, | ||||
|         ) | ||||
|     elif klass is FY5253Quarter: | ||||
|         klass = klass( | ||||
|             n=value, | ||||
|             startingMonth=1, | ||||
|             weekday=1, | ||||
|             qtr_with_extra_week=1, | ||||
|             variation="last", | ||||
|             normalize=normalize, | ||||
|         ) | ||||
|     elif klass is LastWeekOfMonth: | ||||
|         klass = klass(n=value, weekday=5, normalize=normalize) | ||||
|     elif klass is WeekOfMonth: | ||||
|         klass = klass(n=value, week=1, weekday=5, normalize=normalize) | ||||
|     elif klass is Week: | ||||
|         klass = klass(n=value, weekday=5, normalize=normalize) | ||||
|     elif klass is DateOffset: | ||||
|         klass = klass(days=value, normalize=normalize) | ||||
|     else: | ||||
|         klass = klass(value, normalize=normalize) | ||||
|     return klass | ||||
|  | ||||
|  | ||||
| @pytest.fixture( | ||||
|     params=[ | ||||
|         BDay, | ||||
|         BusinessHour, | ||||
|         BMonthEnd, | ||||
|         BMonthBegin, | ||||
|         BQuarterEnd, | ||||
|         BQuarterBegin, | ||||
|         BYearEnd, | ||||
|         BYearBegin, | ||||
|         CDay, | ||||
|         CustomBusinessHour, | ||||
|         CBMonthEnd, | ||||
|         CBMonthBegin, | ||||
|         MonthEnd, | ||||
|         MonthBegin, | ||||
|         SemiMonthBegin, | ||||
|         SemiMonthEnd, | ||||
|         QuarterEnd, | ||||
|         LastWeekOfMonth, | ||||
|         WeekOfMonth, | ||||
|         Week, | ||||
|         YearBegin, | ||||
|         YearEnd, | ||||
|         FY5253, | ||||
|         FY5253Quarter, | ||||
|         DateOffset, | ||||
|     ] | ||||
| ) | ||||
| def _offset(request): | ||||
|     return request.param | ||||
|  | ||||
|  | ||||
| @pytest.fixture | ||||
| def dt(_offset): | ||||
|     if _offset in (CBMonthBegin, CBMonthEnd, BDay): | ||||
|         return Timestamp(2008, 1, 1) | ||||
|     elif _offset is (CustomBusinessHour, BusinessHour): | ||||
|         return Timestamp(2014, 7, 1, 10, 00) | ||||
|     return Timestamp(2008, 1, 2) | ||||
|  | ||||
|  | ||||
| def test_apply_out_of_range(request, tz_naive_fixture, _offset): | ||||
|     tz = tz_naive_fixture | ||||
|  | ||||
|     # try to create an out-of-bounds result timestamp; if we can't create | ||||
|     # the offset skip | ||||
|     try: | ||||
|         if _offset in (BusinessHour, CustomBusinessHour): | ||||
|             # Using 10000 in BusinessHour fails in tz check because of DST | ||||
|             # difference | ||||
|             offset = _get_offset(_offset, value=100000) | ||||
|         else: | ||||
|             offset = _get_offset(_offset, value=10000) | ||||
|  | ||||
|         result = Timestamp("20080101") + offset | ||||
|         assert isinstance(result, datetime) | ||||
|         assert result.tzinfo is None | ||||
|  | ||||
|         # Check tz is preserved | ||||
|         t = Timestamp("20080101", tz=tz) | ||||
|         result = t + offset | ||||
|         assert isinstance(result, datetime) | ||||
|         if tz is not None: | ||||
|             assert t.tzinfo is not None | ||||
|  | ||||
|         if isinstance(tz, tzlocal) and not IS64 and _offset is not DateOffset: | ||||
|             # If we hit OutOfBoundsDatetime on non-64 bit machines | ||||
|             # we'll drop out of the try clause before the next test | ||||
|             request.applymarker( | ||||
|                 pytest.mark.xfail(reason="OverflowError inside tzlocal past 2038") | ||||
|             ) | ||||
|         elif ( | ||||
|             isinstance(tz, tzlocal) | ||||
|             and is_platform_windows() | ||||
|             and _offset in (QuarterEnd, BQuarterBegin, BQuarterEnd) | ||||
|         ): | ||||
|             request.applymarker( | ||||
|                 pytest.mark.xfail(reason="After GH#49737 t.tzinfo is None on CI") | ||||
|             ) | ||||
|         assert str(t.tzinfo) == str(result.tzinfo) | ||||
|  | ||||
|     except OutOfBoundsDatetime: | ||||
|         pass | ||||
|     except (ValueError, KeyError): | ||||
|         # we are creating an invalid offset | ||||
|         # so ignore | ||||
|         pass | ||||
|  | ||||
|  | ||||
| def test_offsets_compare_equal(_offset): | ||||
|     # root cause of GH#456: __ne__ was not implemented | ||||
|     offset1 = _offset() | ||||
|     offset2 = _offset() | ||||
|     assert not offset1 != offset2 | ||||
|     assert offset1 == offset2 | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize( | ||||
|     "date, offset2", | ||||
|     [ | ||||
|         [Timestamp(2008, 1, 1), BDay(2)], | ||||
|         [Timestamp(2014, 7, 1, 10, 00), BusinessHour(n=3)], | ||||
|         [ | ||||
|             Timestamp(2014, 7, 1, 10), | ||||
|             CustomBusinessHour( | ||||
|                 holidays=["2014-06-27", Timestamp(2014, 6, 30), Timestamp("2014-07-02")] | ||||
|             ), | ||||
|         ], | ||||
|         [Timestamp(2008, 1, 2), SemiMonthEnd(2)], | ||||
|         [Timestamp(2008, 1, 2), SemiMonthBegin(2)], | ||||
|         [Timestamp(2008, 1, 2), Week(2)], | ||||
|         [Timestamp(2008, 1, 2), WeekOfMonth(2)], | ||||
|         [Timestamp(2008, 1, 2), LastWeekOfMonth(2)], | ||||
|     ], | ||||
| ) | ||||
| def test_rsub(date, offset2): | ||||
|     assert date - offset2 == (-offset2)._apply(date) | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize( | ||||
|     "date, offset2", | ||||
|     [ | ||||
|         [Timestamp(2008, 1, 1), BDay(2)], | ||||
|         [Timestamp(2014, 7, 1, 10, 00), BusinessHour(n=3)], | ||||
|         [ | ||||
|             Timestamp(2014, 7, 1, 10), | ||||
|             CustomBusinessHour( | ||||
|                 holidays=["2014-06-27", Timestamp(2014, 6, 30), Timestamp("2014-07-02")] | ||||
|             ), | ||||
|         ], | ||||
|         [Timestamp(2008, 1, 2), SemiMonthEnd(2)], | ||||
|         [Timestamp(2008, 1, 2), SemiMonthBegin(2)], | ||||
|         [Timestamp(2008, 1, 2), Week(2)], | ||||
|         [Timestamp(2008, 1, 2), WeekOfMonth(2)], | ||||
|         [Timestamp(2008, 1, 2), LastWeekOfMonth(2)], | ||||
|     ], | ||||
| ) | ||||
| def test_radd(date, offset2): | ||||
|     assert date + offset2 == offset2 + date | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize( | ||||
|     "date, offset_box, offset2", | ||||
|     [ | ||||
|         [Timestamp(2008, 1, 1), BDay, BDay(2)], | ||||
|         [Timestamp(2008, 1, 2), SemiMonthEnd, SemiMonthEnd(2)], | ||||
|         [Timestamp(2008, 1, 2), SemiMonthBegin, SemiMonthBegin(2)], | ||||
|         [Timestamp(2008, 1, 2), Week, Week(2)], | ||||
|         [Timestamp(2008, 1, 2), WeekOfMonth, WeekOfMonth(2)], | ||||
|         [Timestamp(2008, 1, 2), LastWeekOfMonth, LastWeekOfMonth(2)], | ||||
|     ], | ||||
| ) | ||||
| def test_sub(date, offset_box, offset2): | ||||
|     off = offset2 | ||||
|     msg = "Cannot subtract datetime from offset" | ||||
|     with pytest.raises(TypeError, match=msg): | ||||
|         off - date | ||||
|  | ||||
|     assert 2 * off - off == off | ||||
|     assert date - offset2 == date + offset_box(-2) | ||||
|     assert date - offset2 == date - (2 * off - off) | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize( | ||||
|     "offset_box, offset1", | ||||
|     [ | ||||
|         [BDay, BDay()], | ||||
|         [LastWeekOfMonth, LastWeekOfMonth()], | ||||
|         [WeekOfMonth, WeekOfMonth()], | ||||
|         [Week, Week()], | ||||
|         [SemiMonthBegin, SemiMonthBegin()], | ||||
|         [SemiMonthEnd, SemiMonthEnd()], | ||||
|         [CustomBusinessHour, CustomBusinessHour(weekmask="Tue Wed Thu Fri")], | ||||
|         [BusinessHour, BusinessHour()], | ||||
|     ], | ||||
| ) | ||||
| def test_Mult1(offset_box, offset1): | ||||
|     dt = Timestamp(2008, 1, 2) | ||||
|     assert dt + 10 * offset1 == dt + offset_box(10) | ||||
|     assert dt + 5 * offset1 == dt + offset_box(5) | ||||
|  | ||||
|  | ||||
| def test_compare_str(_offset): | ||||
|     # GH#23524 | ||||
|     # comparing to strings that cannot be cast to DateOffsets should | ||||
|     #  not raise for __eq__ or __ne__ | ||||
|     off = _get_offset(_offset) | ||||
|  | ||||
|     assert not off == "infer" | ||||
|     assert off != "foo" | ||||
|     # Note: inequalities are only implemented for Tick subclasses; | ||||
|     #  tests for this are in test_ticks | ||||
| @ -0,0 +1,98 @@ | ||||
| """ | ||||
| Tests for offsets.CustomBusinessDay / CDay | ||||
| """ | ||||
| from datetime import ( | ||||
|     datetime, | ||||
|     timedelta, | ||||
| ) | ||||
|  | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas._libs.tslibs.offsets import CDay | ||||
|  | ||||
| from pandas import ( | ||||
|     _testing as tm, | ||||
|     read_pickle, | ||||
| ) | ||||
| from pandas.tests.tseries.offsets.common import assert_offset_equal | ||||
|  | ||||
| from pandas.tseries.holiday import USFederalHolidayCalendar | ||||
|  | ||||
|  | ||||
| @pytest.fixture | ||||
| def offset(): | ||||
|     return CDay() | ||||
|  | ||||
|  | ||||
| @pytest.fixture | ||||
| def offset2(): | ||||
|     return CDay(2) | ||||
|  | ||||
|  | ||||
| class TestCustomBusinessDay: | ||||
|     def test_repr(self, offset, offset2): | ||||
|         assert repr(offset) == "<CustomBusinessDay>" | ||||
|         assert repr(offset2) == "<2 * CustomBusinessDays>" | ||||
|  | ||||
|         expected = "<BusinessDay: offset=datetime.timedelta(days=1)>" | ||||
|         assert repr(offset + timedelta(1)) == expected | ||||
|  | ||||
|     def test_holidays(self): | ||||
|         # Define a TradingDay offset | ||||
|         holidays = ["2012-05-01", datetime(2013, 5, 1), np.datetime64("2014-05-01")] | ||||
|         tday = CDay(holidays=holidays) | ||||
|         for year in range(2012, 2015): | ||||
|             dt = datetime(year, 4, 30) | ||||
|             xp = datetime(year, 5, 2) | ||||
|             rs = dt + tday | ||||
|             assert rs == xp | ||||
|  | ||||
|     def test_weekmask(self): | ||||
|         weekmask_saudi = "Sat Sun Mon Tue Wed"  # Thu-Fri Weekend | ||||
|         weekmask_uae = "1111001"  # Fri-Sat Weekend | ||||
|         weekmask_egypt = [1, 1, 1, 1, 0, 0, 1]  # Fri-Sat Weekend | ||||
|         bday_saudi = CDay(weekmask=weekmask_saudi) | ||||
|         bday_uae = CDay(weekmask=weekmask_uae) | ||||
|         bday_egypt = CDay(weekmask=weekmask_egypt) | ||||
|         dt = datetime(2013, 5, 1) | ||||
|         xp_saudi = datetime(2013, 5, 4) | ||||
|         xp_uae = datetime(2013, 5, 2) | ||||
|         xp_egypt = datetime(2013, 5, 2) | ||||
|         assert xp_saudi == dt + bday_saudi | ||||
|         assert xp_uae == dt + bday_uae | ||||
|         assert xp_egypt == dt + bday_egypt | ||||
|         xp2 = datetime(2013, 5, 5) | ||||
|         assert xp2 == dt + 2 * bday_saudi | ||||
|         assert xp2 == dt + 2 * bday_uae | ||||
|         assert xp2 == dt + 2 * bday_egypt | ||||
|  | ||||
|     def test_weekmask_and_holidays(self): | ||||
|         weekmask_egypt = "Sun Mon Tue Wed Thu"  # Fri-Sat Weekend | ||||
|         holidays = ["2012-05-01", datetime(2013, 5, 1), np.datetime64("2014-05-01")] | ||||
|         bday_egypt = CDay(holidays=holidays, weekmask=weekmask_egypt) | ||||
|         dt = datetime(2013, 4, 30) | ||||
|         xp_egypt = datetime(2013, 5, 5) | ||||
|         assert xp_egypt == dt + 2 * bday_egypt | ||||
|  | ||||
|     @pytest.mark.filterwarnings("ignore:Non:pandas.errors.PerformanceWarning") | ||||
|     def test_calendar(self): | ||||
|         calendar = USFederalHolidayCalendar() | ||||
|         dt = datetime(2014, 1, 17) | ||||
|         assert_offset_equal(CDay(calendar=calendar), dt, datetime(2014, 1, 21)) | ||||
|  | ||||
|     def test_roundtrip_pickle(self, offset, offset2): | ||||
|         def _check_roundtrip(obj): | ||||
|             unpickled = tm.round_trip_pickle(obj) | ||||
|             assert unpickled == obj | ||||
|  | ||||
|         _check_roundtrip(offset) | ||||
|         _check_roundtrip(offset2) | ||||
|         _check_roundtrip(offset * 2) | ||||
|  | ||||
|     def test_pickle_compat_0_14_1(self, datapath): | ||||
|         hdays = [datetime(2013, 1, 1) for ele in range(4)] | ||||
|         pth = datapath("tseries", "offsets", "data", "cday-0.14.1.pickle") | ||||
|         cday0_14_1 = read_pickle(pth) | ||||
|         cday = CDay(holidays=hdays) | ||||
|         assert cday == cday0_14_1 | ||||
| @ -0,0 +1,329 @@ | ||||
| """ | ||||
| Tests for offsets.CustomBusinessHour | ||||
| """ | ||||
| from __future__ import annotations | ||||
|  | ||||
| from datetime import ( | ||||
|     datetime, | ||||
|     time as dt_time, | ||||
| ) | ||||
|  | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas._libs.tslibs import Timestamp | ||||
| from pandas._libs.tslibs.offsets import ( | ||||
|     BusinessHour, | ||||
|     CustomBusinessHour, | ||||
|     Nano, | ||||
| ) | ||||
|  | ||||
| from pandas.tests.tseries.offsets.common import assert_offset_equal | ||||
|  | ||||
| from pandas.tseries.holiday import USFederalHolidayCalendar | ||||
|  | ||||
| holidays = ["2014-06-27", datetime(2014, 6, 30), np.datetime64("2014-07-02")] | ||||
|  | ||||
|  | ||||
| @pytest.fixture | ||||
| def dt(): | ||||
|     return datetime(2014, 7, 1, 10, 00) | ||||
|  | ||||
|  | ||||
| @pytest.fixture | ||||
| def _offset(): | ||||
|     return CustomBusinessHour | ||||
|  | ||||
|  | ||||
| # 2014 Calendar to check custom holidays | ||||
| #   Sun Mon Tue Wed Thu Fri Sat | ||||
| #  6/22  23  24  25  26  27  28 | ||||
| #    29  30 7/1   2   3   4   5 | ||||
| #     6   7   8   9  10  11  12 | ||||
| @pytest.fixture | ||||
| def offset1(): | ||||
|     return CustomBusinessHour(weekmask="Tue Wed Thu Fri") | ||||
|  | ||||
|  | ||||
| @pytest.fixture | ||||
| def offset2(): | ||||
|     return CustomBusinessHour(holidays=holidays) | ||||
|  | ||||
|  | ||||
| class TestCustomBusinessHour: | ||||
|     def test_constructor_errors(self): | ||||
|         msg = "time data must be specified only with hour and minute" | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             CustomBusinessHour(start=dt_time(11, 0, 5)) | ||||
|         msg = "time data must match '%H:%M' format" | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             CustomBusinessHour(start="AAA") | ||||
|         msg = "time data must match '%H:%M' format" | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             CustomBusinessHour(start="14:00:05") | ||||
|  | ||||
|     def test_different_normalize_equals(self, _offset): | ||||
|         # GH#21404 changed __eq__ to return False when `normalize` does not match | ||||
|         offset = _offset() | ||||
|         offset2 = _offset(normalize=True) | ||||
|         assert offset != offset2 | ||||
|  | ||||
|     def test_repr(self, offset1, offset2): | ||||
|         assert repr(offset1) == "<CustomBusinessHour: cbh=09:00-17:00>" | ||||
|         assert repr(offset2) == "<CustomBusinessHour: cbh=09:00-17:00>" | ||||
|  | ||||
|     def test_with_offset(self, dt): | ||||
|         expected = Timestamp("2014-07-01 13:00") | ||||
|  | ||||
|         assert dt + CustomBusinessHour() * 3 == expected | ||||
|         assert dt + CustomBusinessHour(n=3) == expected | ||||
|  | ||||
|     def test_eq(self, offset1, offset2): | ||||
|         for offset in [offset1, offset2]: | ||||
|             assert offset == offset | ||||
|  | ||||
|         assert CustomBusinessHour() != CustomBusinessHour(-1) | ||||
|         assert CustomBusinessHour(start="09:00") == CustomBusinessHour() | ||||
|         assert CustomBusinessHour(start="09:00") != CustomBusinessHour(start="09:01") | ||||
|         assert CustomBusinessHour(start="09:00", end="17:00") != CustomBusinessHour( | ||||
|             start="17:00", end="09:01" | ||||
|         ) | ||||
|  | ||||
|         assert CustomBusinessHour(weekmask="Tue Wed Thu Fri") != CustomBusinessHour( | ||||
|             weekmask="Mon Tue Wed Thu Fri" | ||||
|         ) | ||||
|         assert CustomBusinessHour(holidays=["2014-06-27"]) != CustomBusinessHour( | ||||
|             holidays=["2014-06-28"] | ||||
|         ) | ||||
|  | ||||
|     def test_hash(self, offset1, offset2): | ||||
|         assert hash(offset1) == hash(offset1) | ||||
|         assert hash(offset2) == hash(offset2) | ||||
|  | ||||
|     def test_add_dateime(self, dt, offset1, offset2): | ||||
|         assert offset1 + dt == datetime(2014, 7, 1, 11) | ||||
|         assert offset2 + dt == datetime(2014, 7, 1, 11) | ||||
|  | ||||
|     def testRollback1(self, dt, offset1, offset2): | ||||
|         assert offset1.rollback(dt) == dt | ||||
|         assert offset2.rollback(dt) == dt | ||||
|  | ||||
|         d = datetime(2014, 7, 1, 0) | ||||
|  | ||||
|         # 2014/07/01 is Tuesday, 06/30 is Monday(holiday) | ||||
|         assert offset1.rollback(d) == datetime(2014, 6, 27, 17) | ||||
|  | ||||
|         # 2014/6/30 and 2014/6/27 are holidays | ||||
|         assert offset2.rollback(d) == datetime(2014, 6, 26, 17) | ||||
|  | ||||
|     def testRollback2(self, _offset): | ||||
|         assert _offset(-3).rollback(datetime(2014, 7, 5, 15, 0)) == datetime( | ||||
|             2014, 7, 4, 17, 0 | ||||
|         ) | ||||
|  | ||||
|     def testRollforward1(self, dt, offset1, offset2): | ||||
|         assert offset1.rollforward(dt) == dt | ||||
|         assert offset2.rollforward(dt) == dt | ||||
|  | ||||
|         d = datetime(2014, 7, 1, 0) | ||||
|         assert offset1.rollforward(d) == datetime(2014, 7, 1, 9) | ||||
|         assert offset2.rollforward(d) == datetime(2014, 7, 1, 9) | ||||
|  | ||||
|     def testRollforward2(self, _offset): | ||||
|         assert _offset(-3).rollforward(datetime(2014, 7, 5, 16, 0)) == datetime( | ||||
|             2014, 7, 7, 9 | ||||
|         ) | ||||
|  | ||||
|     def test_roll_date_object(self): | ||||
|         offset = BusinessHour() | ||||
|  | ||||
|         dt = datetime(2014, 7, 6, 15, 0) | ||||
|  | ||||
|         result = offset.rollback(dt) | ||||
|         assert result == datetime(2014, 7, 4, 17) | ||||
|  | ||||
|         result = offset.rollforward(dt) | ||||
|         assert result == datetime(2014, 7, 7, 9) | ||||
|  | ||||
|     normalize_cases = [ | ||||
|         ( | ||||
|             CustomBusinessHour(normalize=True, holidays=holidays), | ||||
|             { | ||||
|                 datetime(2014, 7, 1, 8): datetime(2014, 7, 1), | ||||
|                 datetime(2014, 7, 1, 17): datetime(2014, 7, 3), | ||||
|                 datetime(2014, 7, 1, 16): datetime(2014, 7, 3), | ||||
|                 datetime(2014, 7, 1, 23): datetime(2014, 7, 3), | ||||
|                 datetime(2014, 7, 1, 0): datetime(2014, 7, 1), | ||||
|                 datetime(2014, 7, 4, 15): datetime(2014, 7, 4), | ||||
|                 datetime(2014, 7, 4, 15, 59): datetime(2014, 7, 4), | ||||
|                 datetime(2014, 7, 4, 16, 30): datetime(2014, 7, 7), | ||||
|                 datetime(2014, 7, 5, 23): datetime(2014, 7, 7), | ||||
|                 datetime(2014, 7, 6, 10): datetime(2014, 7, 7), | ||||
|             }, | ||||
|         ), | ||||
|         ( | ||||
|             CustomBusinessHour(-1, normalize=True, holidays=holidays), | ||||
|             { | ||||
|                 datetime(2014, 7, 1, 8): datetime(2014, 6, 26), | ||||
|                 datetime(2014, 7, 1, 17): datetime(2014, 7, 1), | ||||
|                 datetime(2014, 7, 1, 16): datetime(2014, 7, 1), | ||||
|                 datetime(2014, 7, 1, 10): datetime(2014, 6, 26), | ||||
|                 datetime(2014, 7, 1, 0): datetime(2014, 6, 26), | ||||
|                 datetime(2014, 7, 7, 10): datetime(2014, 7, 4), | ||||
|                 datetime(2014, 7, 7, 10, 1): datetime(2014, 7, 7), | ||||
|                 datetime(2014, 7, 5, 23): datetime(2014, 7, 4), | ||||
|                 datetime(2014, 7, 6, 10): datetime(2014, 7, 4), | ||||
|             }, | ||||
|         ), | ||||
|         ( | ||||
|             CustomBusinessHour( | ||||
|                 1, normalize=True, start="17:00", end="04:00", holidays=holidays | ||||
|             ), | ||||
|             { | ||||
|                 datetime(2014, 7, 1, 8): datetime(2014, 7, 1), | ||||
|                 datetime(2014, 7, 1, 17): datetime(2014, 7, 1), | ||||
|                 datetime(2014, 7, 1, 23): datetime(2014, 7, 2), | ||||
|                 datetime(2014, 7, 2, 2): datetime(2014, 7, 2), | ||||
|                 datetime(2014, 7, 2, 3): datetime(2014, 7, 3), | ||||
|                 datetime(2014, 7, 4, 23): datetime(2014, 7, 5), | ||||
|                 datetime(2014, 7, 5, 2): datetime(2014, 7, 5), | ||||
|                 datetime(2014, 7, 7, 2): datetime(2014, 7, 7), | ||||
|                 datetime(2014, 7, 7, 17): datetime(2014, 7, 7), | ||||
|             }, | ||||
|         ), | ||||
|     ] | ||||
|  | ||||
|     @pytest.mark.parametrize("norm_cases", normalize_cases) | ||||
|     def test_normalize(self, norm_cases): | ||||
|         offset, cases = norm_cases | ||||
|         for dt, expected in cases.items(): | ||||
|             assert offset._apply(dt) == expected | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "dt, expected", | ||||
|         [ | ||||
|             [datetime(2014, 7, 1, 9), False], | ||||
|             [datetime(2014, 7, 1, 10), True], | ||||
|             [datetime(2014, 7, 1, 15), True], | ||||
|             [datetime(2014, 7, 1, 15, 1), False], | ||||
|             [datetime(2014, 7, 5, 12), False], | ||||
|             [datetime(2014, 7, 6, 12), False], | ||||
|         ], | ||||
|     ) | ||||
|     def test_is_on_offset(self, dt, expected): | ||||
|         offset = CustomBusinessHour(start="10:00", end="15:00", holidays=holidays) | ||||
|         assert offset.is_on_offset(dt) == expected | ||||
|  | ||||
|     apply_cases = [ | ||||
|         ( | ||||
|             CustomBusinessHour(holidays=holidays), | ||||
|             { | ||||
|                 datetime(2014, 7, 1, 11): datetime(2014, 7, 1, 12), | ||||
|                 datetime(2014, 7, 1, 13): datetime(2014, 7, 1, 14), | ||||
|                 datetime(2014, 7, 1, 15): datetime(2014, 7, 1, 16), | ||||
|                 datetime(2014, 7, 1, 19): datetime(2014, 7, 3, 10), | ||||
|                 datetime(2014, 7, 1, 16): datetime(2014, 7, 3, 9), | ||||
|                 datetime(2014, 7, 1, 16, 30, 15): datetime(2014, 7, 3, 9, 30, 15), | ||||
|                 datetime(2014, 7, 1, 17): datetime(2014, 7, 3, 10), | ||||
|                 datetime(2014, 7, 2, 11): datetime(2014, 7, 3, 10), | ||||
|                 # out of business hours | ||||
|                 datetime(2014, 7, 2, 8): datetime(2014, 7, 3, 10), | ||||
|                 datetime(2014, 7, 2, 19): datetime(2014, 7, 3, 10), | ||||
|                 datetime(2014, 7, 2, 23): datetime(2014, 7, 3, 10), | ||||
|                 datetime(2014, 7, 3, 0): datetime(2014, 7, 3, 10), | ||||
|                 # saturday | ||||
|                 datetime(2014, 7, 5, 15): datetime(2014, 7, 7, 10), | ||||
|                 datetime(2014, 7, 4, 17): datetime(2014, 7, 7, 10), | ||||
|                 datetime(2014, 7, 4, 16, 30): datetime(2014, 7, 7, 9, 30), | ||||
|                 datetime(2014, 7, 4, 16, 30, 30): datetime(2014, 7, 7, 9, 30, 30), | ||||
|             }, | ||||
|         ), | ||||
|         ( | ||||
|             CustomBusinessHour(4, holidays=holidays), | ||||
|             { | ||||
|                 datetime(2014, 7, 1, 11): datetime(2014, 7, 1, 15), | ||||
|                 datetime(2014, 7, 1, 13): datetime(2014, 7, 3, 9), | ||||
|                 datetime(2014, 7, 1, 15): datetime(2014, 7, 3, 11), | ||||
|                 datetime(2014, 7, 1, 16): datetime(2014, 7, 3, 12), | ||||
|                 datetime(2014, 7, 1, 17): datetime(2014, 7, 3, 13), | ||||
|                 datetime(2014, 7, 2, 11): datetime(2014, 7, 3, 13), | ||||
|                 datetime(2014, 7, 2, 8): datetime(2014, 7, 3, 13), | ||||
|                 datetime(2014, 7, 2, 19): datetime(2014, 7, 3, 13), | ||||
|                 datetime(2014, 7, 2, 23): datetime(2014, 7, 3, 13), | ||||
|                 datetime(2014, 7, 3, 0): datetime(2014, 7, 3, 13), | ||||
|                 datetime(2014, 7, 5, 15): datetime(2014, 7, 7, 13), | ||||
|                 datetime(2014, 7, 4, 17): datetime(2014, 7, 7, 13), | ||||
|                 datetime(2014, 7, 4, 16, 30): datetime(2014, 7, 7, 12, 30), | ||||
|                 datetime(2014, 7, 4, 16, 30, 30): datetime(2014, 7, 7, 12, 30, 30), | ||||
|             }, | ||||
|         ), | ||||
|     ] | ||||
|  | ||||
|     @pytest.mark.parametrize("apply_case", apply_cases) | ||||
|     def test_apply(self, apply_case): | ||||
|         offset, cases = apply_case | ||||
|         for base, expected in cases.items(): | ||||
|             assert_offset_equal(offset, base, expected) | ||||
|  | ||||
|     nano_cases = [ | ||||
|         ( | ||||
|             CustomBusinessHour(holidays=holidays), | ||||
|             { | ||||
|                 Timestamp("2014-07-01 15:00") | ||||
|                 + Nano(5): Timestamp("2014-07-01 16:00") | ||||
|                 + Nano(5), | ||||
|                 Timestamp("2014-07-01 16:00") | ||||
|                 + Nano(5): Timestamp("2014-07-03 09:00") | ||||
|                 + Nano(5), | ||||
|                 Timestamp("2014-07-01 16:00") | ||||
|                 - Nano(5): Timestamp("2014-07-01 17:00") | ||||
|                 - Nano(5), | ||||
|             }, | ||||
|         ), | ||||
|         ( | ||||
|             CustomBusinessHour(-1, holidays=holidays), | ||||
|             { | ||||
|                 Timestamp("2014-07-01 15:00") | ||||
|                 + Nano(5): Timestamp("2014-07-01 14:00") | ||||
|                 + Nano(5), | ||||
|                 Timestamp("2014-07-01 10:00") | ||||
|                 + Nano(5): Timestamp("2014-07-01 09:00") | ||||
|                 + Nano(5), | ||||
|                 Timestamp("2014-07-01 10:00") | ||||
|                 - Nano(5): Timestamp("2014-06-26 17:00") | ||||
|                 - Nano(5), | ||||
|             }, | ||||
|         ), | ||||
|     ] | ||||
|  | ||||
|     @pytest.mark.parametrize("nano_case", nano_cases) | ||||
|     def test_apply_nanoseconds(self, nano_case): | ||||
|         offset, cases = nano_case | ||||
|         for base, expected in cases.items(): | ||||
|             assert_offset_equal(offset, base, expected) | ||||
|  | ||||
|     def test_us_federal_holiday_with_datetime(self): | ||||
|         # GH 16867 | ||||
|         bhour_us = CustomBusinessHour(calendar=USFederalHolidayCalendar()) | ||||
|         t0 = datetime(2014, 1, 17, 15) | ||||
|         result = t0 + bhour_us * 8 | ||||
|         expected = Timestamp("2014-01-21 15:00:00") | ||||
|         assert result == expected | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize( | ||||
|     "weekmask, expected_time, mult", | ||||
|     [ | ||||
|         ["Mon Tue Wed Thu Fri Sat", "2018-11-10 09:00:00", 10], | ||||
|         ["Tue Wed Thu Fri Sat", "2018-11-13 08:00:00", 18], | ||||
|     ], | ||||
| ) | ||||
| def test_custom_businesshour_weekmask_and_holidays(weekmask, expected_time, mult): | ||||
|     # GH 23542 | ||||
|     holidays = ["2018-11-09"] | ||||
|     bh = CustomBusinessHour( | ||||
|         start="08:00", end="17:00", weekmask=weekmask, holidays=holidays | ||||
|     ) | ||||
|     result = Timestamp("2018-11-08 08:00") + mult * bh | ||||
|     expected = Timestamp(expected_time) | ||||
|     assert result == expected | ||||
| @ -0,0 +1,437 @@ | ||||
| """ | ||||
| Tests for the following offsets: | ||||
| - CustomBusinessMonthBase | ||||
| - CustomBusinessMonthBegin | ||||
| - CustomBusinessMonthEnd | ||||
| """ | ||||
| from __future__ import annotations | ||||
|  | ||||
| from datetime import ( | ||||
|     date, | ||||
|     datetime, | ||||
|     timedelta, | ||||
| ) | ||||
|  | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas._libs.tslibs.offsets import ( | ||||
|     CBMonthBegin, | ||||
|     CBMonthEnd, | ||||
|     CDay, | ||||
| ) | ||||
|  | ||||
| import pandas._testing as tm | ||||
| from pandas.tests.tseries.offsets.common import ( | ||||
|     assert_is_on_offset, | ||||
|     assert_offset_equal, | ||||
| ) | ||||
|  | ||||
| from pandas.tseries import offsets | ||||
|  | ||||
|  | ||||
| @pytest.fixture | ||||
| def dt(): | ||||
|     return datetime(2008, 1, 1) | ||||
|  | ||||
|  | ||||
| class TestCommonCBM: | ||||
|     @pytest.mark.parametrize("offset2", [CBMonthBegin(2), CBMonthEnd(2)]) | ||||
|     def test_eq(self, offset2): | ||||
|         assert offset2 == offset2 | ||||
|  | ||||
|     @pytest.mark.parametrize("offset2", [CBMonthBegin(2), CBMonthEnd(2)]) | ||||
|     def test_hash(self, offset2): | ||||
|         assert hash(offset2) == hash(offset2) | ||||
|  | ||||
|     @pytest.mark.parametrize("_offset", [CBMonthBegin, CBMonthEnd]) | ||||
|     def test_roundtrip_pickle(self, _offset): | ||||
|         def _check_roundtrip(obj): | ||||
|             unpickled = tm.round_trip_pickle(obj) | ||||
|             assert unpickled == obj | ||||
|  | ||||
|         _check_roundtrip(_offset()) | ||||
|         _check_roundtrip(_offset(2)) | ||||
|         _check_roundtrip(_offset() * 2) | ||||
|  | ||||
|     @pytest.mark.parametrize("_offset", [CBMonthBegin, CBMonthEnd]) | ||||
|     def test_copy(self, _offset): | ||||
|         # GH 17452 | ||||
|         off = _offset(weekmask="Mon Wed Fri") | ||||
|         assert off == off.copy() | ||||
|  | ||||
|  | ||||
| class TestCustomBusinessMonthBegin: | ||||
|     @pytest.fixture | ||||
|     def _offset(self): | ||||
|         return CBMonthBegin | ||||
|  | ||||
|     @pytest.fixture | ||||
|     def offset(self): | ||||
|         return CBMonthBegin() | ||||
|  | ||||
|     @pytest.fixture | ||||
|     def offset2(self): | ||||
|         return CBMonthBegin(2) | ||||
|  | ||||
|     def test_different_normalize_equals(self, _offset): | ||||
|         # GH#21404 changed __eq__ to return False when `normalize` does not match | ||||
|         offset = _offset() | ||||
|         offset2 = _offset(normalize=True) | ||||
|         assert offset != offset2 | ||||
|  | ||||
|     def test_repr(self, offset, offset2): | ||||
|         assert repr(offset) == "<CustomBusinessMonthBegin>" | ||||
|         assert repr(offset2) == "<2 * CustomBusinessMonthBegins>" | ||||
|  | ||||
|     def test_add_datetime(self, dt, offset2): | ||||
|         assert offset2 + dt == datetime(2008, 3, 3) | ||||
|  | ||||
|     def testRollback1(self): | ||||
|         assert CDay(10).rollback(datetime(2007, 12, 31)) == datetime(2007, 12, 31) | ||||
|  | ||||
|     def testRollback2(self, dt): | ||||
|         assert CBMonthBegin(10).rollback(dt) == datetime(2008, 1, 1) | ||||
|  | ||||
|     def testRollforward1(self, dt): | ||||
|         assert CBMonthBegin(10).rollforward(dt) == datetime(2008, 1, 1) | ||||
|  | ||||
|     def test_roll_date_object(self): | ||||
|         offset = CBMonthBegin() | ||||
|  | ||||
|         dt = date(2012, 9, 15) | ||||
|  | ||||
|         result = offset.rollback(dt) | ||||
|         assert result == datetime(2012, 9, 3) | ||||
|  | ||||
|         result = offset.rollforward(dt) | ||||
|         assert result == datetime(2012, 10, 1) | ||||
|  | ||||
|         offset = offsets.Day() | ||||
|         result = offset.rollback(dt) | ||||
|         assert result == datetime(2012, 9, 15) | ||||
|  | ||||
|         result = offset.rollforward(dt) | ||||
|         assert result == datetime(2012, 9, 15) | ||||
|  | ||||
|     on_offset_cases = [ | ||||
|         (CBMonthBegin(), datetime(2008, 1, 1), True), | ||||
|         (CBMonthBegin(), datetime(2008, 1, 31), False), | ||||
|     ] | ||||
|  | ||||
|     @pytest.mark.parametrize("case", on_offset_cases) | ||||
|     def test_is_on_offset(self, case): | ||||
|         offset, dt, expected = case | ||||
|         assert_is_on_offset(offset, dt, expected) | ||||
|  | ||||
|     apply_cases = [ | ||||
|         ( | ||||
|             CBMonthBegin(), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 2, 1), | ||||
|                 datetime(2008, 2, 7): datetime(2008, 3, 3), | ||||
|             }, | ||||
|         ), | ||||
|         ( | ||||
|             2 * CBMonthBegin(), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 3, 3), | ||||
|                 datetime(2008, 2, 7): datetime(2008, 4, 1), | ||||
|             }, | ||||
|         ), | ||||
|         ( | ||||
|             -CBMonthBegin(), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2007, 12, 3), | ||||
|                 datetime(2008, 2, 8): datetime(2008, 2, 1), | ||||
|             }, | ||||
|         ), | ||||
|         ( | ||||
|             -2 * CBMonthBegin(), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2007, 11, 1), | ||||
|                 datetime(2008, 2, 9): datetime(2008, 1, 1), | ||||
|             }, | ||||
|         ), | ||||
|         ( | ||||
|             CBMonthBegin(0), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 1), | ||||
|                 datetime(2008, 1, 7): datetime(2008, 2, 1), | ||||
|             }, | ||||
|         ), | ||||
|     ] | ||||
|  | ||||
|     @pytest.mark.parametrize("case", apply_cases) | ||||
|     def test_apply(self, case): | ||||
|         offset, cases = case | ||||
|         for base, expected in cases.items(): | ||||
|             assert_offset_equal(offset, base, expected) | ||||
|  | ||||
|     def test_apply_large_n(self): | ||||
|         dt = datetime(2012, 10, 23) | ||||
|  | ||||
|         result = dt + CBMonthBegin(10) | ||||
|         assert result == datetime(2013, 8, 1) | ||||
|  | ||||
|         result = dt + CDay(100) - CDay(100) | ||||
|         assert result == dt | ||||
|  | ||||
|         off = CBMonthBegin() * 6 | ||||
|         rs = datetime(2012, 1, 1) - off | ||||
|         xp = datetime(2011, 7, 1) | ||||
|         assert rs == xp | ||||
|  | ||||
|         st = datetime(2011, 12, 18) | ||||
|         rs = st + off | ||||
|  | ||||
|         xp = datetime(2012, 6, 1) | ||||
|         assert rs == xp | ||||
|  | ||||
|     def test_holidays(self): | ||||
|         # Define a TradingDay offset | ||||
|         holidays = ["2012-02-01", datetime(2012, 2, 2), np.datetime64("2012-03-01")] | ||||
|         bm_offset = CBMonthBegin(holidays=holidays) | ||||
|         dt = datetime(2012, 1, 1) | ||||
|  | ||||
|         assert dt + bm_offset == datetime(2012, 1, 2) | ||||
|         assert dt + 2 * bm_offset == datetime(2012, 2, 3) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "case", | ||||
|         [ | ||||
|             ( | ||||
|                 CBMonthBegin(n=1, offset=timedelta(days=5)), | ||||
|                 { | ||||
|                     datetime(2021, 3, 1): datetime(2021, 4, 1) + timedelta(days=5), | ||||
|                     datetime(2021, 4, 17): datetime(2021, 5, 3) + timedelta(days=5), | ||||
|                 }, | ||||
|             ), | ||||
|             ( | ||||
|                 CBMonthBegin(n=2, offset=timedelta(days=40)), | ||||
|                 { | ||||
|                     datetime(2021, 3, 10): datetime(2021, 5, 3) + timedelta(days=40), | ||||
|                     datetime(2021, 4, 30): datetime(2021, 6, 1) + timedelta(days=40), | ||||
|                 }, | ||||
|             ), | ||||
|             ( | ||||
|                 CBMonthBegin(n=1, offset=timedelta(days=-5)), | ||||
|                 { | ||||
|                     datetime(2021, 3, 1): datetime(2021, 4, 1) - timedelta(days=5), | ||||
|                     datetime(2021, 4, 11): datetime(2021, 5, 3) - timedelta(days=5), | ||||
|                 }, | ||||
|             ), | ||||
|             ( | ||||
|                 -2 * CBMonthBegin(n=1, offset=timedelta(days=10)), | ||||
|                 { | ||||
|                     datetime(2021, 3, 1): datetime(2021, 1, 1) + timedelta(days=10), | ||||
|                     datetime(2021, 4, 3): datetime(2021, 3, 1) + timedelta(days=10), | ||||
|                 }, | ||||
|             ), | ||||
|             ( | ||||
|                 CBMonthBegin(n=0, offset=timedelta(days=1)), | ||||
|                 { | ||||
|                     datetime(2021, 3, 2): datetime(2021, 4, 1) + timedelta(days=1), | ||||
|                     datetime(2021, 4, 1): datetime(2021, 4, 1) + timedelta(days=1), | ||||
|                 }, | ||||
|             ), | ||||
|             ( | ||||
|                 CBMonthBegin( | ||||
|                     n=1, holidays=["2021-04-01", "2021-04-02"], offset=timedelta(days=1) | ||||
|                 ), | ||||
|                 { | ||||
|                     datetime(2021, 3, 2): datetime(2021, 4, 5) + timedelta(days=1), | ||||
|                 }, | ||||
|             ), | ||||
|         ], | ||||
|     ) | ||||
|     def test_apply_with_extra_offset(self, case): | ||||
|         offset, cases = case | ||||
|         for base, expected in cases.items(): | ||||
|             assert_offset_equal(offset, base, expected) | ||||
|  | ||||
|  | ||||
| class TestCustomBusinessMonthEnd: | ||||
|     @pytest.fixture | ||||
|     def _offset(self): | ||||
|         return CBMonthEnd | ||||
|  | ||||
|     @pytest.fixture | ||||
|     def offset(self): | ||||
|         return CBMonthEnd() | ||||
|  | ||||
|     @pytest.fixture | ||||
|     def offset2(self): | ||||
|         return CBMonthEnd(2) | ||||
|  | ||||
|     def test_different_normalize_equals(self, _offset): | ||||
|         # GH#21404 changed __eq__ to return False when `normalize` does not match | ||||
|         offset = _offset() | ||||
|         offset2 = _offset(normalize=True) | ||||
|         assert offset != offset2 | ||||
|  | ||||
|     def test_repr(self, offset, offset2): | ||||
|         assert repr(offset) == "<CustomBusinessMonthEnd>" | ||||
|         assert repr(offset2) == "<2 * CustomBusinessMonthEnds>" | ||||
|  | ||||
|     def test_add_datetime(self, dt, offset2): | ||||
|         assert offset2 + dt == datetime(2008, 2, 29) | ||||
|  | ||||
|     def testRollback1(self): | ||||
|         assert CDay(10).rollback(datetime(2007, 12, 31)) == datetime(2007, 12, 31) | ||||
|  | ||||
|     def testRollback2(self, dt): | ||||
|         assert CBMonthEnd(10).rollback(dt) == datetime(2007, 12, 31) | ||||
|  | ||||
|     def testRollforward1(self, dt): | ||||
|         assert CBMonthEnd(10).rollforward(dt) == datetime(2008, 1, 31) | ||||
|  | ||||
|     def test_roll_date_object(self): | ||||
|         offset = CBMonthEnd() | ||||
|  | ||||
|         dt = date(2012, 9, 15) | ||||
|  | ||||
|         result = offset.rollback(dt) | ||||
|         assert result == datetime(2012, 8, 31) | ||||
|  | ||||
|         result = offset.rollforward(dt) | ||||
|         assert result == datetime(2012, 9, 28) | ||||
|  | ||||
|         offset = offsets.Day() | ||||
|         result = offset.rollback(dt) | ||||
|         assert result == datetime(2012, 9, 15) | ||||
|  | ||||
|         result = offset.rollforward(dt) | ||||
|         assert result == datetime(2012, 9, 15) | ||||
|  | ||||
|     on_offset_cases = [ | ||||
|         (CBMonthEnd(), datetime(2008, 1, 31), True), | ||||
|         (CBMonthEnd(), datetime(2008, 1, 1), False), | ||||
|     ] | ||||
|  | ||||
|     @pytest.mark.parametrize("case", on_offset_cases) | ||||
|     def test_is_on_offset(self, case): | ||||
|         offset, dt, expected = case | ||||
|         assert_is_on_offset(offset, dt, expected) | ||||
|  | ||||
|     apply_cases = [ | ||||
|         ( | ||||
|             CBMonthEnd(), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 31), | ||||
|                 datetime(2008, 2, 7): datetime(2008, 2, 29), | ||||
|             }, | ||||
|         ), | ||||
|         ( | ||||
|             2 * CBMonthEnd(), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 2, 29), | ||||
|                 datetime(2008, 2, 7): datetime(2008, 3, 31), | ||||
|             }, | ||||
|         ), | ||||
|         ( | ||||
|             -CBMonthEnd(), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2007, 12, 31), | ||||
|                 datetime(2008, 2, 8): datetime(2008, 1, 31), | ||||
|             }, | ||||
|         ), | ||||
|         ( | ||||
|             -2 * CBMonthEnd(), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2007, 11, 30), | ||||
|                 datetime(2008, 2, 9): datetime(2007, 12, 31), | ||||
|             }, | ||||
|         ), | ||||
|         ( | ||||
|             CBMonthEnd(0), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 31), | ||||
|                 datetime(2008, 2, 7): datetime(2008, 2, 29), | ||||
|             }, | ||||
|         ), | ||||
|     ] | ||||
|  | ||||
|     @pytest.mark.parametrize("case", apply_cases) | ||||
|     def test_apply(self, case): | ||||
|         offset, cases = case | ||||
|         for base, expected in cases.items(): | ||||
|             assert_offset_equal(offset, base, expected) | ||||
|  | ||||
|     def test_apply_large_n(self): | ||||
|         dt = datetime(2012, 10, 23) | ||||
|  | ||||
|         result = dt + CBMonthEnd(10) | ||||
|         assert result == datetime(2013, 7, 31) | ||||
|  | ||||
|         result = dt + CDay(100) - CDay(100) | ||||
|         assert result == dt | ||||
|  | ||||
|         off = CBMonthEnd() * 6 | ||||
|         rs = datetime(2012, 1, 1) - off | ||||
|         xp = datetime(2011, 7, 29) | ||||
|         assert rs == xp | ||||
|  | ||||
|         st = datetime(2011, 12, 18) | ||||
|         rs = st + off | ||||
|         xp = datetime(2012, 5, 31) | ||||
|         assert rs == xp | ||||
|  | ||||
|     def test_holidays(self): | ||||
|         # Define a TradingDay offset | ||||
|         holidays = ["2012-01-31", datetime(2012, 2, 28), np.datetime64("2012-02-29")] | ||||
|         bm_offset = CBMonthEnd(holidays=holidays) | ||||
|         dt = datetime(2012, 1, 1) | ||||
|         assert dt + bm_offset == datetime(2012, 1, 30) | ||||
|         assert dt + 2 * bm_offset == datetime(2012, 2, 27) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "case", | ||||
|         [ | ||||
|             ( | ||||
|                 CBMonthEnd(n=1, offset=timedelta(days=5)), | ||||
|                 { | ||||
|                     datetime(2021, 3, 1): datetime(2021, 3, 31) + timedelta(days=5), | ||||
|                     datetime(2021, 4, 17): datetime(2021, 4, 30) + timedelta(days=5), | ||||
|                 }, | ||||
|             ), | ||||
|             ( | ||||
|                 CBMonthEnd(n=2, offset=timedelta(days=40)), | ||||
|                 { | ||||
|                     datetime(2021, 3, 10): datetime(2021, 4, 30) + timedelta(days=40), | ||||
|                     datetime(2021, 4, 30): datetime(2021, 6, 30) + timedelta(days=40), | ||||
|                 }, | ||||
|             ), | ||||
|             ( | ||||
|                 CBMonthEnd(n=1, offset=timedelta(days=-5)), | ||||
|                 { | ||||
|                     datetime(2021, 3, 1): datetime(2021, 3, 31) - timedelta(days=5), | ||||
|                     datetime(2021, 4, 11): datetime(2021, 4, 30) - timedelta(days=5), | ||||
|                 }, | ||||
|             ), | ||||
|             ( | ||||
|                 -2 * CBMonthEnd(n=1, offset=timedelta(days=10)), | ||||
|                 { | ||||
|                     datetime(2021, 3, 1): datetime(2021, 1, 29) + timedelta(days=10), | ||||
|                     datetime(2021, 4, 3): datetime(2021, 2, 26) + timedelta(days=10), | ||||
|                 }, | ||||
|             ), | ||||
|             ( | ||||
|                 CBMonthEnd(n=0, offset=timedelta(days=1)), | ||||
|                 { | ||||
|                     datetime(2021, 3, 2): datetime(2021, 3, 31) + timedelta(days=1), | ||||
|                     datetime(2021, 4, 1): datetime(2021, 4, 30) + timedelta(days=1), | ||||
|                 }, | ||||
|             ), | ||||
|             ( | ||||
|                 CBMonthEnd(n=1, holidays=["2021-03-31"], offset=timedelta(days=1)), | ||||
|                 { | ||||
|                     datetime(2021, 3, 2): datetime(2021, 3, 30) + timedelta(days=1), | ||||
|                 }, | ||||
|             ), | ||||
|         ], | ||||
|     ) | ||||
|     def test_apply_with_extra_offset(self, case): | ||||
|         offset, cases = case | ||||
|         for base, expected in cases.items(): | ||||
|             assert_offset_equal(offset, base, expected) | ||||
| @ -0,0 +1,260 @@ | ||||
| """ | ||||
| Tests for DateOffset additions over Daylight Savings Time | ||||
| """ | ||||
| from datetime import timedelta | ||||
|  | ||||
| import pytest | ||||
| import pytz | ||||
|  | ||||
| from pandas._libs.tslibs import Timestamp | ||||
| from pandas._libs.tslibs.offsets import ( | ||||
|     BMonthBegin, | ||||
|     BMonthEnd, | ||||
|     BQuarterBegin, | ||||
|     BQuarterEnd, | ||||
|     BYearBegin, | ||||
|     BYearEnd, | ||||
|     CBMonthBegin, | ||||
|     CBMonthEnd, | ||||
|     CustomBusinessDay, | ||||
|     DateOffset, | ||||
|     Day, | ||||
|     MonthBegin, | ||||
|     MonthEnd, | ||||
|     QuarterBegin, | ||||
|     QuarterEnd, | ||||
|     SemiMonthBegin, | ||||
|     SemiMonthEnd, | ||||
|     Week, | ||||
|     YearBegin, | ||||
|     YearEnd, | ||||
| ) | ||||
| from pandas.errors import PerformanceWarning | ||||
|  | ||||
| from pandas import DatetimeIndex | ||||
| import pandas._testing as tm | ||||
| from pandas.util.version import Version | ||||
|  | ||||
| # error: Module has no attribute "__version__" | ||||
| pytz_version = Version(pytz.__version__)  # type: ignore[attr-defined] | ||||
|  | ||||
|  | ||||
| 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 | ||||
|  | ||||
|  | ||||
| class TestDST: | ||||
|     # one microsecond before the DST transition | ||||
|     ts_pre_fallback = "2013-11-03 01:59:59.999999" | ||||
|     ts_pre_springfwd = "2013-03-10 01:59:59.999999" | ||||
|  | ||||
|     # test both basic names and dateutil timezones | ||||
|     timezone_utc_offsets = { | ||||
|         "US/Eastern": {"utc_offset_daylight": -4, "utc_offset_standard": -5}, | ||||
|         "dateutil/US/Pacific": {"utc_offset_daylight": -7, "utc_offset_standard": -8}, | ||||
|     } | ||||
|     valid_date_offsets_singular = [ | ||||
|         "weekday", | ||||
|         "day", | ||||
|         "hour", | ||||
|         "minute", | ||||
|         "second", | ||||
|         "microsecond", | ||||
|     ] | ||||
|     valid_date_offsets_plural = [ | ||||
|         "weeks", | ||||
|         "days", | ||||
|         "hours", | ||||
|         "minutes", | ||||
|         "seconds", | ||||
|         "milliseconds", | ||||
|         "microseconds", | ||||
|     ] | ||||
|  | ||||
|     def _test_all_offsets(self, n, **kwds): | ||||
|         valid_offsets = ( | ||||
|             self.valid_date_offsets_plural | ||||
|             if n > 1 | ||||
|             else self.valid_date_offsets_singular | ||||
|         ) | ||||
|  | ||||
|         for name in valid_offsets: | ||||
|             self._test_offset(offset_name=name, offset_n=n, **kwds) | ||||
|  | ||||
|     def _test_offset(self, offset_name, offset_n, tstart, expected_utc_offset): | ||||
|         offset = DateOffset(**{offset_name: offset_n}) | ||||
|  | ||||
|         if ( | ||||
|             offset_name in ["hour", "minute", "second", "microsecond"] | ||||
|             and offset_n == 1 | ||||
|             and tstart == Timestamp("2013-11-03 01:59:59.999999-0500", tz="US/Eastern") | ||||
|         ): | ||||
|             # This addition results in an ambiguous wall time | ||||
|             err_msg = { | ||||
|                 "hour": "2013-11-03 01:59:59.999999", | ||||
|                 "minute": "2013-11-03 01:01:59.999999", | ||||
|                 "second": "2013-11-03 01:59:01.999999", | ||||
|                 "microsecond": "2013-11-03 01:59:59.000001", | ||||
|             }[offset_name] | ||||
|             with pytest.raises(pytz.AmbiguousTimeError, match=err_msg): | ||||
|                 tstart + offset | ||||
|             # While we're here, let's check that we get the same behavior in a | ||||
|             #  vectorized path | ||||
|             dti = DatetimeIndex([tstart]) | ||||
|             warn_msg = "Non-vectorized DateOffset" | ||||
|             with pytest.raises(pytz.AmbiguousTimeError, match=err_msg): | ||||
|                 with tm.assert_produces_warning(PerformanceWarning, match=warn_msg): | ||||
|                     dti + offset | ||||
|             return | ||||
|  | ||||
|         t = tstart + offset | ||||
|         if expected_utc_offset is not None: | ||||
|             assert get_utc_offset_hours(t) == expected_utc_offset | ||||
|  | ||||
|         if offset_name == "weeks": | ||||
|             # dates should match | ||||
|             assert t.date() == timedelta(days=7 * offset.kwds["weeks"]) + tstart.date() | ||||
|             # expect the same day of week, hour of day, minute, second, ... | ||||
|             assert ( | ||||
|                 t.dayofweek == tstart.dayofweek | ||||
|                 and t.hour == tstart.hour | ||||
|                 and t.minute == tstart.minute | ||||
|                 and t.second == tstart.second | ||||
|             ) | ||||
|         elif offset_name == "days": | ||||
|             # dates should match | ||||
|             assert timedelta(offset.kwds["days"]) + tstart.date() == t.date() | ||||
|             # expect the same hour of day, minute, second, ... | ||||
|             assert ( | ||||
|                 t.hour == tstart.hour | ||||
|                 and t.minute == tstart.minute | ||||
|                 and t.second == tstart.second | ||||
|             ) | ||||
|         elif offset_name in self.valid_date_offsets_singular: | ||||
|             # expect the singular offset value to match between tstart and t | ||||
|             datepart_offset = getattr( | ||||
|                 t, offset_name if offset_name != "weekday" else "dayofweek" | ||||
|             ) | ||||
|             assert datepart_offset == offset.kwds[offset_name] | ||||
|         else: | ||||
|             # the offset should be the same as if it was done in UTC | ||||
|             assert t == (tstart.tz_convert("UTC") + offset).tz_convert("US/Pacific") | ||||
|  | ||||
|     def _make_timestamp(self, string, hrs_offset, tz): | ||||
|         if hrs_offset >= 0: | ||||
|             offset_string = f"{hrs_offset:02d}00" | ||||
|         else: | ||||
|             offset_string = f"-{(hrs_offset * -1):02}00" | ||||
|         return Timestamp(string + offset_string).tz_convert(tz) | ||||
|  | ||||
|     def test_springforward_plural(self): | ||||
|         # test moving from standard to daylight savings | ||||
|         for tz, utc_offsets in self.timezone_utc_offsets.items(): | ||||
|             hrs_pre = utc_offsets["utc_offset_standard"] | ||||
|             hrs_post = utc_offsets["utc_offset_daylight"] | ||||
|             self._test_all_offsets( | ||||
|                 n=3, | ||||
|                 tstart=self._make_timestamp(self.ts_pre_springfwd, hrs_pre, tz), | ||||
|                 expected_utc_offset=hrs_post, | ||||
|             ) | ||||
|  | ||||
|     def test_fallback_singular(self): | ||||
|         # in the case of singular offsets, we don't necessarily know which utc | ||||
|         # offset the new Timestamp will wind up in (the tz for 1 month may be | ||||
|         # different from 1 second) so we don't specify an expected_utc_offset | ||||
|         for tz, utc_offsets in self.timezone_utc_offsets.items(): | ||||
|             hrs_pre = utc_offsets["utc_offset_standard"] | ||||
|             self._test_all_offsets( | ||||
|                 n=1, | ||||
|                 tstart=self._make_timestamp(self.ts_pre_fallback, hrs_pre, tz), | ||||
|                 expected_utc_offset=None, | ||||
|             ) | ||||
|  | ||||
|     def test_springforward_singular(self): | ||||
|         for tz, utc_offsets in self.timezone_utc_offsets.items(): | ||||
|             hrs_pre = utc_offsets["utc_offset_standard"] | ||||
|             self._test_all_offsets( | ||||
|                 n=1, | ||||
|                 tstart=self._make_timestamp(self.ts_pre_springfwd, hrs_pre, tz), | ||||
|                 expected_utc_offset=None, | ||||
|             ) | ||||
|  | ||||
|     offset_classes = { | ||||
|         MonthBegin: ["11/2/2012", "12/1/2012"], | ||||
|         MonthEnd: ["11/2/2012", "11/30/2012"], | ||||
|         BMonthBegin: ["11/2/2012", "12/3/2012"], | ||||
|         BMonthEnd: ["11/2/2012", "11/30/2012"], | ||||
|         CBMonthBegin: ["11/2/2012", "12/3/2012"], | ||||
|         CBMonthEnd: ["11/2/2012", "11/30/2012"], | ||||
|         SemiMonthBegin: ["11/2/2012", "11/15/2012"], | ||||
|         SemiMonthEnd: ["11/2/2012", "11/15/2012"], | ||||
|         Week: ["11/2/2012", "11/9/2012"], | ||||
|         YearBegin: ["11/2/2012", "1/1/2013"], | ||||
|         YearEnd: ["11/2/2012", "12/31/2012"], | ||||
|         BYearBegin: ["11/2/2012", "1/1/2013"], | ||||
|         BYearEnd: ["11/2/2012", "12/31/2012"], | ||||
|         QuarterBegin: ["11/2/2012", "12/1/2012"], | ||||
|         QuarterEnd: ["11/2/2012", "12/31/2012"], | ||||
|         BQuarterBegin: ["11/2/2012", "12/3/2012"], | ||||
|         BQuarterEnd: ["11/2/2012", "12/31/2012"], | ||||
|         Day: ["11/4/2012", "11/4/2012 23:00"], | ||||
|     }.items() | ||||
|  | ||||
|     @pytest.mark.parametrize("tup", offset_classes) | ||||
|     def test_all_offset_classes(self, tup): | ||||
|         offset, test_values = tup | ||||
|  | ||||
|         first = Timestamp(test_values[0], tz="US/Eastern") + offset() | ||||
|         second = Timestamp(test_values[1], tz="US/Eastern") | ||||
|         assert first == second | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize( | ||||
|     "original_dt, target_dt, offset, tz", | ||||
|     [ | ||||
|         pytest.param( | ||||
|             Timestamp("1900-01-01"), | ||||
|             Timestamp("1905-07-01"), | ||||
|             MonthBegin(66), | ||||
|             "Africa/Lagos", | ||||
|             marks=pytest.mark.xfail( | ||||
|                 pytz_version < Version("2020.5") or pytz_version == Version("2022.2"), | ||||
|                 reason="GH#41906: pytz utc transition dates changed", | ||||
|             ), | ||||
|         ), | ||||
|         ( | ||||
|             Timestamp("2021-10-01 01:15"), | ||||
|             Timestamp("2021-10-31 01:15"), | ||||
|             MonthEnd(1), | ||||
|             "Europe/London", | ||||
|         ), | ||||
|         ( | ||||
|             Timestamp("2010-12-05 02:59"), | ||||
|             Timestamp("2010-10-31 02:59"), | ||||
|             SemiMonthEnd(-3), | ||||
|             "Europe/Paris", | ||||
|         ), | ||||
|         ( | ||||
|             Timestamp("2021-10-31 01:20"), | ||||
|             Timestamp("2021-11-07 01:20"), | ||||
|             CustomBusinessDay(2, weekmask="Sun Mon"), | ||||
|             "US/Eastern", | ||||
|         ), | ||||
|         ( | ||||
|             Timestamp("2020-04-03 01:30"), | ||||
|             Timestamp("2020-11-01 01:30"), | ||||
|             YearBegin(1, month=11), | ||||
|             "America/Chicago", | ||||
|         ), | ||||
|     ], | ||||
| ) | ||||
| def test_nontick_offset_with_ambiguous_time_error(original_dt, target_dt, offset, tz): | ||||
|     # .apply for non-Tick offsets throws AmbiguousTimeError when the target dt | ||||
|     # is dst-ambiguous | ||||
|     localized_dt = original_dt.tz_localize(tz) | ||||
|  | ||||
|     msg = f"Cannot infer dst time from {target_dt}, try using the 'ambiguous' argument" | ||||
|     with pytest.raises(pytz.AmbiguousTimeError, match=msg): | ||||
|         localized_dt + offset | ||||
| @ -0,0 +1,33 @@ | ||||
| """ | ||||
| Tests for the following offsets: | ||||
| - Easter | ||||
| """ | ||||
| from __future__ import annotations | ||||
|  | ||||
| from datetime import datetime | ||||
|  | ||||
| import pytest | ||||
|  | ||||
| from pandas.tests.tseries.offsets.common import assert_offset_equal | ||||
|  | ||||
| from pandas.tseries.offsets import Easter | ||||
|  | ||||
|  | ||||
| class TestEaster: | ||||
|     @pytest.mark.parametrize( | ||||
|         "offset,date,expected", | ||||
|         [ | ||||
|             (Easter(), datetime(2010, 1, 1), datetime(2010, 4, 4)), | ||||
|             (Easter(), datetime(2010, 4, 5), datetime(2011, 4, 24)), | ||||
|             (Easter(2), datetime(2010, 1, 1), datetime(2011, 4, 24)), | ||||
|             (Easter(), datetime(2010, 4, 4), datetime(2011, 4, 24)), | ||||
|             (Easter(2), datetime(2010, 4, 4), datetime(2012, 4, 8)), | ||||
|             (-Easter(), datetime(2011, 1, 1), datetime(2010, 4, 4)), | ||||
|             (-Easter(), datetime(2010, 4, 5), datetime(2010, 4, 4)), | ||||
|             (-Easter(2), datetime(2011, 1, 1), datetime(2009, 4, 12)), | ||||
|             (-Easter(), datetime(2010, 4, 4), datetime(2009, 4, 12)), | ||||
|             (-Easter(2), datetime(2010, 4, 4), datetime(2008, 3, 23)), | ||||
|         ], | ||||
|     ) | ||||
|     def test_offset(self, offset, date, expected): | ||||
|         assert_offset_equal(offset, date, expected) | ||||
| @ -0,0 +1,656 @@ | ||||
| """ | ||||
| Tests for Fiscal Year and Fiscal Quarter offset classes | ||||
| """ | ||||
| from datetime import datetime | ||||
|  | ||||
| from dateutil.relativedelta import relativedelta | ||||
| import pytest | ||||
|  | ||||
| from pandas import Timestamp | ||||
| import pandas._testing as tm | ||||
| from pandas.tests.tseries.offsets.common import ( | ||||
|     WeekDay, | ||||
|     assert_is_on_offset, | ||||
|     assert_offset_equal, | ||||
| ) | ||||
|  | ||||
| from pandas.tseries.offsets import ( | ||||
|     FY5253, | ||||
|     FY5253Quarter, | ||||
| ) | ||||
|  | ||||
|  | ||||
| def makeFY5253LastOfMonthQuarter(*args, **kwds): | ||||
|     return FY5253Quarter(*args, variation="last", **kwds) | ||||
|  | ||||
|  | ||||
| def makeFY5253NearestEndMonthQuarter(*args, **kwds): | ||||
|     return FY5253Quarter(*args, variation="nearest", **kwds) | ||||
|  | ||||
|  | ||||
| def makeFY5253NearestEndMonth(*args, **kwds): | ||||
|     return FY5253(*args, variation="nearest", **kwds) | ||||
|  | ||||
|  | ||||
| def makeFY5253LastOfMonth(*args, **kwds): | ||||
|     return FY5253(*args, variation="last", **kwds) | ||||
|  | ||||
|  | ||||
| def test_get_offset_name(): | ||||
|     assert ( | ||||
|         makeFY5253LastOfMonthQuarter( | ||||
|             weekday=1, startingMonth=3, qtr_with_extra_week=4 | ||||
|         ).freqstr | ||||
|         == "REQ-L-MAR-TUE-4" | ||||
|     ) | ||||
|     assert ( | ||||
|         makeFY5253NearestEndMonthQuarter( | ||||
|             weekday=1, startingMonth=3, qtr_with_extra_week=3 | ||||
|         ).freqstr | ||||
|         == "REQ-N-MAR-TUE-3" | ||||
|     ) | ||||
|  | ||||
|  | ||||
| class TestFY5253LastOfMonth: | ||||
|     offset_lom_sat_aug = makeFY5253LastOfMonth(1, startingMonth=8, weekday=WeekDay.SAT) | ||||
|     offset_lom_sat_sep = makeFY5253LastOfMonth(1, startingMonth=9, weekday=WeekDay.SAT) | ||||
|  | ||||
|     on_offset_cases = [ | ||||
|         # From Wikipedia (see: | ||||
|         # https://en.wikipedia.org/wiki/4%E2%80%934%E2%80%935_calendar#Last_Saturday_of_the_month_at_fiscal_year_end) | ||||
|         (offset_lom_sat_aug, datetime(2006, 8, 26), True), | ||||
|         (offset_lom_sat_aug, datetime(2007, 8, 25), True), | ||||
|         (offset_lom_sat_aug, datetime(2008, 8, 30), True), | ||||
|         (offset_lom_sat_aug, datetime(2009, 8, 29), True), | ||||
|         (offset_lom_sat_aug, datetime(2010, 8, 28), True), | ||||
|         (offset_lom_sat_aug, datetime(2011, 8, 27), True), | ||||
|         (offset_lom_sat_aug, datetime(2012, 8, 25), True), | ||||
|         (offset_lom_sat_aug, datetime(2013, 8, 31), True), | ||||
|         (offset_lom_sat_aug, datetime(2014, 8, 30), True), | ||||
|         (offset_lom_sat_aug, datetime(2015, 8, 29), True), | ||||
|         (offset_lom_sat_aug, datetime(2016, 8, 27), True), | ||||
|         (offset_lom_sat_aug, datetime(2017, 8, 26), True), | ||||
|         (offset_lom_sat_aug, datetime(2018, 8, 25), True), | ||||
|         (offset_lom_sat_aug, datetime(2019, 8, 31), True), | ||||
|         (offset_lom_sat_aug, datetime(2006, 8, 27), False), | ||||
|         (offset_lom_sat_aug, datetime(2007, 8, 28), False), | ||||
|         (offset_lom_sat_aug, datetime(2008, 8, 31), False), | ||||
|         (offset_lom_sat_aug, datetime(2009, 8, 30), False), | ||||
|         (offset_lom_sat_aug, datetime(2010, 8, 29), False), | ||||
|         (offset_lom_sat_aug, datetime(2011, 8, 28), False), | ||||
|         (offset_lom_sat_aug, datetime(2006, 8, 25), False), | ||||
|         (offset_lom_sat_aug, datetime(2007, 8, 24), False), | ||||
|         (offset_lom_sat_aug, datetime(2008, 8, 29), False), | ||||
|         (offset_lom_sat_aug, datetime(2009, 8, 28), False), | ||||
|         (offset_lom_sat_aug, datetime(2010, 8, 27), False), | ||||
|         (offset_lom_sat_aug, datetime(2011, 8, 26), False), | ||||
|         (offset_lom_sat_aug, datetime(2019, 8, 30), False), | ||||
|         # From GMCR (see for example: | ||||
|         # http://yahoo.brand.edgar-online.com/Default.aspx? | ||||
|         # companyid=3184&formtypeID=7) | ||||
|         (offset_lom_sat_sep, datetime(2010, 9, 25), True), | ||||
|         (offset_lom_sat_sep, datetime(2011, 9, 24), True), | ||||
|         (offset_lom_sat_sep, datetime(2012, 9, 29), True), | ||||
|     ] | ||||
|  | ||||
|     @pytest.mark.parametrize("case", on_offset_cases) | ||||
|     def test_is_on_offset(self, case): | ||||
|         offset, dt, expected = case | ||||
|         assert_is_on_offset(offset, dt, expected) | ||||
|  | ||||
|     def test_apply(self): | ||||
|         offset_lom_aug_sat = makeFY5253LastOfMonth(startingMonth=8, weekday=WeekDay.SAT) | ||||
|         offset_lom_aug_sat_1 = makeFY5253LastOfMonth( | ||||
|             n=1, startingMonth=8, weekday=WeekDay.SAT | ||||
|         ) | ||||
|  | ||||
|         date_seq_lom_aug_sat = [ | ||||
|             datetime(2006, 8, 26), | ||||
|             datetime(2007, 8, 25), | ||||
|             datetime(2008, 8, 30), | ||||
|             datetime(2009, 8, 29), | ||||
|             datetime(2010, 8, 28), | ||||
|             datetime(2011, 8, 27), | ||||
|             datetime(2012, 8, 25), | ||||
|             datetime(2013, 8, 31), | ||||
|             datetime(2014, 8, 30), | ||||
|             datetime(2015, 8, 29), | ||||
|             datetime(2016, 8, 27), | ||||
|         ] | ||||
|  | ||||
|         tests = [ | ||||
|             (offset_lom_aug_sat, date_seq_lom_aug_sat), | ||||
|             (offset_lom_aug_sat_1, date_seq_lom_aug_sat), | ||||
|             (offset_lom_aug_sat, [datetime(2006, 8, 25)] + date_seq_lom_aug_sat), | ||||
|             (offset_lom_aug_sat_1, [datetime(2006, 8, 27)] + date_seq_lom_aug_sat[1:]), | ||||
|             ( | ||||
|                 makeFY5253LastOfMonth(n=-1, startingMonth=8, weekday=WeekDay.SAT), | ||||
|                 list(reversed(date_seq_lom_aug_sat)), | ||||
|             ), | ||||
|         ] | ||||
|         for test in tests: | ||||
|             offset, data = test | ||||
|             current = data[0] | ||||
|             for datum in data[1:]: | ||||
|                 current = current + offset | ||||
|                 assert current == datum | ||||
|  | ||||
|  | ||||
| class TestFY5253NearestEndMonth: | ||||
|     def test_get_year_end(self): | ||||
|         assert makeFY5253NearestEndMonth( | ||||
|             startingMonth=8, weekday=WeekDay.SAT | ||||
|         ).get_year_end(datetime(2013, 1, 1)) == datetime(2013, 8, 31) | ||||
|         assert makeFY5253NearestEndMonth( | ||||
|             startingMonth=8, weekday=WeekDay.SUN | ||||
|         ).get_year_end(datetime(2013, 1, 1)) == datetime(2013, 9, 1) | ||||
|         assert makeFY5253NearestEndMonth( | ||||
|             startingMonth=8, weekday=WeekDay.FRI | ||||
|         ).get_year_end(datetime(2013, 1, 1)) == datetime(2013, 8, 30) | ||||
|  | ||||
|         offset_n = FY5253(weekday=WeekDay.TUE, startingMonth=12, variation="nearest") | ||||
|         assert offset_n.get_year_end(datetime(2012, 1, 1)) == datetime(2013, 1, 1) | ||||
|         assert offset_n.get_year_end(datetime(2012, 1, 10)) == datetime(2013, 1, 1) | ||||
|  | ||||
|         assert offset_n.get_year_end(datetime(2013, 1, 1)) == datetime(2013, 12, 31) | ||||
|         assert offset_n.get_year_end(datetime(2013, 1, 2)) == datetime(2013, 12, 31) | ||||
|         assert offset_n.get_year_end(datetime(2013, 1, 3)) == datetime(2013, 12, 31) | ||||
|         assert offset_n.get_year_end(datetime(2013, 1, 10)) == datetime(2013, 12, 31) | ||||
|  | ||||
|         JNJ = FY5253(n=1, startingMonth=12, weekday=6, variation="nearest") | ||||
|         assert JNJ.get_year_end(datetime(2006, 1, 1)) == datetime(2006, 12, 31) | ||||
|  | ||||
|     offset_lom_aug_sat = makeFY5253NearestEndMonth( | ||||
|         1, startingMonth=8, weekday=WeekDay.SAT | ||||
|     ) | ||||
|     offset_lom_aug_thu = makeFY5253NearestEndMonth( | ||||
|         1, startingMonth=8, weekday=WeekDay.THU | ||||
|     ) | ||||
|     offset_n = FY5253(weekday=WeekDay.TUE, startingMonth=12, variation="nearest") | ||||
|  | ||||
|     on_offset_cases = [ | ||||
|         #    From Wikipedia (see: | ||||
|         #    https://en.wikipedia.org/wiki/4%E2%80%934%E2%80%935_calendar | ||||
|         #    #Saturday_nearest_the_end_of_month) | ||||
|         #    2006-09-02   2006 September 2 | ||||
|         #    2007-09-01   2007 September 1 | ||||
|         #    2008-08-30   2008 August 30    (leap year) | ||||
|         #    2009-08-29   2009 August 29 | ||||
|         #    2010-08-28   2010 August 28 | ||||
|         #    2011-09-03   2011 September 3 | ||||
|         #    2012-09-01   2012 September 1  (leap year) | ||||
|         #    2013-08-31   2013 August 31 | ||||
|         #    2014-08-30   2014 August 30 | ||||
|         #    2015-08-29   2015 August 29 | ||||
|         #    2016-09-03   2016 September 3  (leap year) | ||||
|         #    2017-09-02   2017 September 2 | ||||
|         #    2018-09-01   2018 September 1 | ||||
|         #    2019-08-31   2019 August 31 | ||||
|         (offset_lom_aug_sat, datetime(2006, 9, 2), True), | ||||
|         (offset_lom_aug_sat, datetime(2007, 9, 1), True), | ||||
|         (offset_lom_aug_sat, datetime(2008, 8, 30), True), | ||||
|         (offset_lom_aug_sat, datetime(2009, 8, 29), True), | ||||
|         (offset_lom_aug_sat, datetime(2010, 8, 28), True), | ||||
|         (offset_lom_aug_sat, datetime(2011, 9, 3), True), | ||||
|         (offset_lom_aug_sat, datetime(2016, 9, 3), True), | ||||
|         (offset_lom_aug_sat, datetime(2017, 9, 2), True), | ||||
|         (offset_lom_aug_sat, datetime(2018, 9, 1), True), | ||||
|         (offset_lom_aug_sat, datetime(2019, 8, 31), True), | ||||
|         (offset_lom_aug_sat, datetime(2006, 8, 27), False), | ||||
|         (offset_lom_aug_sat, datetime(2007, 8, 28), False), | ||||
|         (offset_lom_aug_sat, datetime(2008, 8, 31), False), | ||||
|         (offset_lom_aug_sat, datetime(2009, 8, 30), False), | ||||
|         (offset_lom_aug_sat, datetime(2010, 8, 29), False), | ||||
|         (offset_lom_aug_sat, datetime(2011, 8, 28), False), | ||||
|         (offset_lom_aug_sat, datetime(2006, 8, 25), False), | ||||
|         (offset_lom_aug_sat, datetime(2007, 8, 24), False), | ||||
|         (offset_lom_aug_sat, datetime(2008, 8, 29), False), | ||||
|         (offset_lom_aug_sat, datetime(2009, 8, 28), False), | ||||
|         (offset_lom_aug_sat, datetime(2010, 8, 27), False), | ||||
|         (offset_lom_aug_sat, datetime(2011, 8, 26), False), | ||||
|         (offset_lom_aug_sat, datetime(2019, 8, 30), False), | ||||
|         # From Micron, see: | ||||
|         # http://google.brand.edgar-online.com/?sym=MU&formtypeID=7 | ||||
|         (offset_lom_aug_thu, datetime(2012, 8, 30), True), | ||||
|         (offset_lom_aug_thu, datetime(2011, 9, 1), True), | ||||
|         (offset_n, datetime(2012, 12, 31), False), | ||||
|         (offset_n, datetime(2013, 1, 1), True), | ||||
|         (offset_n, datetime(2013, 1, 2), False), | ||||
|     ] | ||||
|  | ||||
|     @pytest.mark.parametrize("case", on_offset_cases) | ||||
|     def test_is_on_offset(self, case): | ||||
|         offset, dt, expected = case | ||||
|         assert_is_on_offset(offset, dt, expected) | ||||
|  | ||||
|     def test_apply(self): | ||||
|         date_seq_nem_8_sat = [ | ||||
|             datetime(2006, 9, 2), | ||||
|             datetime(2007, 9, 1), | ||||
|             datetime(2008, 8, 30), | ||||
|             datetime(2009, 8, 29), | ||||
|             datetime(2010, 8, 28), | ||||
|             datetime(2011, 9, 3), | ||||
|         ] | ||||
|  | ||||
|         JNJ = [ | ||||
|             datetime(2005, 1, 2), | ||||
|             datetime(2006, 1, 1), | ||||
|             datetime(2006, 12, 31), | ||||
|             datetime(2007, 12, 30), | ||||
|             datetime(2008, 12, 28), | ||||
|             datetime(2010, 1, 3), | ||||
|             datetime(2011, 1, 2), | ||||
|             datetime(2012, 1, 1), | ||||
|             datetime(2012, 12, 30), | ||||
|         ] | ||||
|  | ||||
|         DEC_SAT = FY5253(n=-1, startingMonth=12, weekday=5, variation="nearest") | ||||
|  | ||||
|         tests = [ | ||||
|             ( | ||||
|                 makeFY5253NearestEndMonth(startingMonth=8, weekday=WeekDay.SAT), | ||||
|                 date_seq_nem_8_sat, | ||||
|             ), | ||||
|             ( | ||||
|                 makeFY5253NearestEndMonth(n=1, startingMonth=8, weekday=WeekDay.SAT), | ||||
|                 date_seq_nem_8_sat, | ||||
|             ), | ||||
|             ( | ||||
|                 makeFY5253NearestEndMonth(startingMonth=8, weekday=WeekDay.SAT), | ||||
|                 [datetime(2006, 9, 1)] + date_seq_nem_8_sat, | ||||
|             ), | ||||
|             ( | ||||
|                 makeFY5253NearestEndMonth(n=1, startingMonth=8, weekday=WeekDay.SAT), | ||||
|                 [datetime(2006, 9, 3)] + date_seq_nem_8_sat[1:], | ||||
|             ), | ||||
|             ( | ||||
|                 makeFY5253NearestEndMonth(n=-1, startingMonth=8, weekday=WeekDay.SAT), | ||||
|                 list(reversed(date_seq_nem_8_sat)), | ||||
|             ), | ||||
|             ( | ||||
|                 makeFY5253NearestEndMonth(n=1, startingMonth=12, weekday=WeekDay.SUN), | ||||
|                 JNJ, | ||||
|             ), | ||||
|             ( | ||||
|                 makeFY5253NearestEndMonth(n=-1, startingMonth=12, weekday=WeekDay.SUN), | ||||
|                 list(reversed(JNJ)), | ||||
|             ), | ||||
|             ( | ||||
|                 makeFY5253NearestEndMonth(n=1, startingMonth=12, weekday=WeekDay.SUN), | ||||
|                 [datetime(2005, 1, 2), datetime(2006, 1, 1)], | ||||
|             ), | ||||
|             ( | ||||
|                 makeFY5253NearestEndMonth(n=1, startingMonth=12, weekday=WeekDay.SUN), | ||||
|                 [datetime(2006, 1, 2), datetime(2006, 12, 31)], | ||||
|             ), | ||||
|             (DEC_SAT, [datetime(2013, 1, 15), datetime(2012, 12, 29)]), | ||||
|         ] | ||||
|         for test in tests: | ||||
|             offset, data = test | ||||
|             current = data[0] | ||||
|             for datum in data[1:]: | ||||
|                 current = current + offset | ||||
|                 assert current == datum | ||||
|  | ||||
|  | ||||
| class TestFY5253LastOfMonthQuarter: | ||||
|     def test_is_anchored(self): | ||||
|         msg = "FY5253Quarter.is_anchored is deprecated " | ||||
|  | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             assert makeFY5253LastOfMonthQuarter( | ||||
|                 startingMonth=1, weekday=WeekDay.SAT, qtr_with_extra_week=4 | ||||
|             ).is_anchored() | ||||
|             assert makeFY5253LastOfMonthQuarter( | ||||
|                 weekday=WeekDay.SAT, startingMonth=3, qtr_with_extra_week=4 | ||||
|             ).is_anchored() | ||||
|             assert not makeFY5253LastOfMonthQuarter( | ||||
|                 2, startingMonth=1, weekday=WeekDay.SAT, qtr_with_extra_week=4 | ||||
|             ).is_anchored() | ||||
|  | ||||
|     def test_equality(self): | ||||
|         assert makeFY5253LastOfMonthQuarter( | ||||
|             startingMonth=1, weekday=WeekDay.SAT, qtr_with_extra_week=4 | ||||
|         ) == makeFY5253LastOfMonthQuarter( | ||||
|             startingMonth=1, weekday=WeekDay.SAT, qtr_with_extra_week=4 | ||||
|         ) | ||||
|         assert makeFY5253LastOfMonthQuarter( | ||||
|             startingMonth=1, weekday=WeekDay.SAT, qtr_with_extra_week=4 | ||||
|         ) != makeFY5253LastOfMonthQuarter( | ||||
|             startingMonth=1, weekday=WeekDay.SUN, qtr_with_extra_week=4 | ||||
|         ) | ||||
|         assert makeFY5253LastOfMonthQuarter( | ||||
|             startingMonth=1, weekday=WeekDay.SAT, qtr_with_extra_week=4 | ||||
|         ) != makeFY5253LastOfMonthQuarter( | ||||
|             startingMonth=2, weekday=WeekDay.SAT, qtr_with_extra_week=4 | ||||
|         ) | ||||
|  | ||||
|     def test_offset(self): | ||||
|         offset = makeFY5253LastOfMonthQuarter( | ||||
|             1, startingMonth=9, weekday=WeekDay.SAT, qtr_with_extra_week=4 | ||||
|         ) | ||||
|         offset2 = makeFY5253LastOfMonthQuarter( | ||||
|             2, startingMonth=9, weekday=WeekDay.SAT, qtr_with_extra_week=4 | ||||
|         ) | ||||
|         offset4 = makeFY5253LastOfMonthQuarter( | ||||
|             4, startingMonth=9, weekday=WeekDay.SAT, qtr_with_extra_week=4 | ||||
|         ) | ||||
|  | ||||
|         offset_neg1 = makeFY5253LastOfMonthQuarter( | ||||
|             -1, startingMonth=9, weekday=WeekDay.SAT, qtr_with_extra_week=4 | ||||
|         ) | ||||
|         offset_neg2 = makeFY5253LastOfMonthQuarter( | ||||
|             -2, startingMonth=9, weekday=WeekDay.SAT, qtr_with_extra_week=4 | ||||
|         ) | ||||
|  | ||||
|         GMCR = [ | ||||
|             datetime(2010, 3, 27), | ||||
|             datetime(2010, 6, 26), | ||||
|             datetime(2010, 9, 25), | ||||
|             datetime(2010, 12, 25), | ||||
|             datetime(2011, 3, 26), | ||||
|             datetime(2011, 6, 25), | ||||
|             datetime(2011, 9, 24), | ||||
|             datetime(2011, 12, 24), | ||||
|             datetime(2012, 3, 24), | ||||
|             datetime(2012, 6, 23), | ||||
|             datetime(2012, 9, 29), | ||||
|             datetime(2012, 12, 29), | ||||
|             datetime(2013, 3, 30), | ||||
|             datetime(2013, 6, 29), | ||||
|         ] | ||||
|  | ||||
|         assert_offset_equal(offset, base=GMCR[0], expected=GMCR[1]) | ||||
|         assert_offset_equal( | ||||
|             offset, base=GMCR[0] + relativedelta(days=-1), expected=GMCR[0] | ||||
|         ) | ||||
|         assert_offset_equal(offset, base=GMCR[1], expected=GMCR[2]) | ||||
|  | ||||
|         assert_offset_equal(offset2, base=GMCR[0], expected=GMCR[2]) | ||||
|         assert_offset_equal(offset4, base=GMCR[0], expected=GMCR[4]) | ||||
|  | ||||
|         assert_offset_equal(offset_neg1, base=GMCR[-1], expected=GMCR[-2]) | ||||
|         assert_offset_equal( | ||||
|             offset_neg1, base=GMCR[-1] + relativedelta(days=+1), expected=GMCR[-1] | ||||
|         ) | ||||
|         assert_offset_equal(offset_neg2, base=GMCR[-1], expected=GMCR[-3]) | ||||
|  | ||||
|         date = GMCR[0] + relativedelta(days=-1) | ||||
|         for expected in GMCR: | ||||
|             assert_offset_equal(offset, date, expected) | ||||
|             date = date + offset | ||||
|  | ||||
|         date = GMCR[-1] + relativedelta(days=+1) | ||||
|         for expected in reversed(GMCR): | ||||
|             assert_offset_equal(offset_neg1, date, expected) | ||||
|             date = date + offset_neg1 | ||||
|  | ||||
|     lomq_aug_sat_4 = makeFY5253LastOfMonthQuarter( | ||||
|         1, startingMonth=8, weekday=WeekDay.SAT, qtr_with_extra_week=4 | ||||
|     ) | ||||
|     lomq_sep_sat_4 = makeFY5253LastOfMonthQuarter( | ||||
|         1, startingMonth=9, weekday=WeekDay.SAT, qtr_with_extra_week=4 | ||||
|     ) | ||||
|  | ||||
|     on_offset_cases = [ | ||||
|         # From Wikipedia | ||||
|         (lomq_aug_sat_4, datetime(2006, 8, 26), True), | ||||
|         (lomq_aug_sat_4, datetime(2007, 8, 25), True), | ||||
|         (lomq_aug_sat_4, datetime(2008, 8, 30), True), | ||||
|         (lomq_aug_sat_4, datetime(2009, 8, 29), True), | ||||
|         (lomq_aug_sat_4, datetime(2010, 8, 28), True), | ||||
|         (lomq_aug_sat_4, datetime(2011, 8, 27), True), | ||||
|         (lomq_aug_sat_4, datetime(2019, 8, 31), True), | ||||
|         (lomq_aug_sat_4, datetime(2006, 8, 27), False), | ||||
|         (lomq_aug_sat_4, datetime(2007, 8, 28), False), | ||||
|         (lomq_aug_sat_4, datetime(2008, 8, 31), False), | ||||
|         (lomq_aug_sat_4, datetime(2009, 8, 30), False), | ||||
|         (lomq_aug_sat_4, datetime(2010, 8, 29), False), | ||||
|         (lomq_aug_sat_4, datetime(2011, 8, 28), False), | ||||
|         (lomq_aug_sat_4, datetime(2006, 8, 25), False), | ||||
|         (lomq_aug_sat_4, datetime(2007, 8, 24), False), | ||||
|         (lomq_aug_sat_4, datetime(2008, 8, 29), False), | ||||
|         (lomq_aug_sat_4, datetime(2009, 8, 28), False), | ||||
|         (lomq_aug_sat_4, datetime(2010, 8, 27), False), | ||||
|         (lomq_aug_sat_4, datetime(2011, 8, 26), False), | ||||
|         (lomq_aug_sat_4, datetime(2019, 8, 30), False), | ||||
|         # From GMCR | ||||
|         (lomq_sep_sat_4, datetime(2010, 9, 25), True), | ||||
|         (lomq_sep_sat_4, datetime(2011, 9, 24), True), | ||||
|         (lomq_sep_sat_4, datetime(2012, 9, 29), True), | ||||
|         (lomq_sep_sat_4, datetime(2013, 6, 29), True), | ||||
|         (lomq_sep_sat_4, datetime(2012, 6, 23), True), | ||||
|         (lomq_sep_sat_4, datetime(2012, 6, 30), False), | ||||
|         (lomq_sep_sat_4, datetime(2013, 3, 30), True), | ||||
|         (lomq_sep_sat_4, datetime(2012, 3, 24), True), | ||||
|         (lomq_sep_sat_4, datetime(2012, 12, 29), True), | ||||
|         (lomq_sep_sat_4, datetime(2011, 12, 24), True), | ||||
|         # INTC (extra week in Q1) | ||||
|         # See: http://www.intc.com/releasedetail.cfm?ReleaseID=542844 | ||||
|         ( | ||||
|             makeFY5253LastOfMonthQuarter( | ||||
|                 1, startingMonth=12, weekday=WeekDay.SAT, qtr_with_extra_week=1 | ||||
|             ), | ||||
|             datetime(2011, 4, 2), | ||||
|             True, | ||||
|         ), | ||||
|         # see: http://google.brand.edgar-online.com/?sym=INTC&formtypeID=7 | ||||
|         ( | ||||
|             makeFY5253LastOfMonthQuarter( | ||||
|                 1, startingMonth=12, weekday=WeekDay.SAT, qtr_with_extra_week=1 | ||||
|             ), | ||||
|             datetime(2012, 12, 29), | ||||
|             True, | ||||
|         ), | ||||
|         ( | ||||
|             makeFY5253LastOfMonthQuarter( | ||||
|                 1, startingMonth=12, weekday=WeekDay.SAT, qtr_with_extra_week=1 | ||||
|             ), | ||||
|             datetime(2011, 12, 31), | ||||
|             True, | ||||
|         ), | ||||
|         ( | ||||
|             makeFY5253LastOfMonthQuarter( | ||||
|                 1, startingMonth=12, weekday=WeekDay.SAT, qtr_with_extra_week=1 | ||||
|             ), | ||||
|             datetime(2010, 12, 25), | ||||
|             True, | ||||
|         ), | ||||
|     ] | ||||
|  | ||||
|     @pytest.mark.parametrize("case", on_offset_cases) | ||||
|     def test_is_on_offset(self, case): | ||||
|         offset, dt, expected = case | ||||
|         assert_is_on_offset(offset, dt, expected) | ||||
|  | ||||
|     def test_year_has_extra_week(self): | ||||
|         # End of long Q1 | ||||
|         assert makeFY5253LastOfMonthQuarter( | ||||
|             1, startingMonth=12, weekday=WeekDay.SAT, qtr_with_extra_week=1 | ||||
|         ).year_has_extra_week(datetime(2011, 4, 2)) | ||||
|  | ||||
|         # Start of long Q1 | ||||
|         assert makeFY5253LastOfMonthQuarter( | ||||
|             1, startingMonth=12, weekday=WeekDay.SAT, qtr_with_extra_week=1 | ||||
|         ).year_has_extra_week(datetime(2010, 12, 26)) | ||||
|  | ||||
|         # End of year before year with long Q1 | ||||
|         assert not makeFY5253LastOfMonthQuarter( | ||||
|             1, startingMonth=12, weekday=WeekDay.SAT, qtr_with_extra_week=1 | ||||
|         ).year_has_extra_week(datetime(2010, 12, 25)) | ||||
|  | ||||
|         for year in [ | ||||
|             x for x in range(1994, 2011 + 1) if x not in [2011, 2005, 2000, 1994] | ||||
|         ]: | ||||
|             assert not makeFY5253LastOfMonthQuarter( | ||||
|                 1, startingMonth=12, weekday=WeekDay.SAT, qtr_with_extra_week=1 | ||||
|             ).year_has_extra_week(datetime(year, 4, 2)) | ||||
|  | ||||
|         # Other long years | ||||
|         assert makeFY5253LastOfMonthQuarter( | ||||
|             1, startingMonth=12, weekday=WeekDay.SAT, qtr_with_extra_week=1 | ||||
|         ).year_has_extra_week(datetime(2005, 4, 2)) | ||||
|  | ||||
|         assert makeFY5253LastOfMonthQuarter( | ||||
|             1, startingMonth=12, weekday=WeekDay.SAT, qtr_with_extra_week=1 | ||||
|         ).year_has_extra_week(datetime(2000, 4, 2)) | ||||
|  | ||||
|         assert makeFY5253LastOfMonthQuarter( | ||||
|             1, startingMonth=12, weekday=WeekDay.SAT, qtr_with_extra_week=1 | ||||
|         ).year_has_extra_week(datetime(1994, 4, 2)) | ||||
|  | ||||
|     def test_get_weeks(self): | ||||
|         sat_dec_1 = makeFY5253LastOfMonthQuarter( | ||||
|             1, startingMonth=12, weekday=WeekDay.SAT, qtr_with_extra_week=1 | ||||
|         ) | ||||
|         sat_dec_4 = makeFY5253LastOfMonthQuarter( | ||||
|             1, startingMonth=12, weekday=WeekDay.SAT, qtr_with_extra_week=4 | ||||
|         ) | ||||
|  | ||||
|         assert sat_dec_1.get_weeks(datetime(2011, 4, 2)) == [14, 13, 13, 13] | ||||
|         assert sat_dec_4.get_weeks(datetime(2011, 4, 2)) == [13, 13, 13, 14] | ||||
|         assert sat_dec_1.get_weeks(datetime(2010, 12, 25)) == [13, 13, 13, 13] | ||||
|  | ||||
|  | ||||
| class TestFY5253NearestEndMonthQuarter: | ||||
|     offset_nem_sat_aug_4 = makeFY5253NearestEndMonthQuarter( | ||||
|         1, startingMonth=8, weekday=WeekDay.SAT, qtr_with_extra_week=4 | ||||
|     ) | ||||
|     offset_nem_thu_aug_4 = makeFY5253NearestEndMonthQuarter( | ||||
|         1, startingMonth=8, weekday=WeekDay.THU, qtr_with_extra_week=4 | ||||
|     ) | ||||
|     offset_n = FY5253(weekday=WeekDay.TUE, startingMonth=12, variation="nearest") | ||||
|  | ||||
|     on_offset_cases = [ | ||||
|         # From Wikipedia | ||||
|         (offset_nem_sat_aug_4, datetime(2006, 9, 2), True), | ||||
|         (offset_nem_sat_aug_4, datetime(2007, 9, 1), True), | ||||
|         (offset_nem_sat_aug_4, datetime(2008, 8, 30), True), | ||||
|         (offset_nem_sat_aug_4, datetime(2009, 8, 29), True), | ||||
|         (offset_nem_sat_aug_4, datetime(2010, 8, 28), True), | ||||
|         (offset_nem_sat_aug_4, datetime(2011, 9, 3), True), | ||||
|         (offset_nem_sat_aug_4, datetime(2016, 9, 3), True), | ||||
|         (offset_nem_sat_aug_4, datetime(2017, 9, 2), True), | ||||
|         (offset_nem_sat_aug_4, datetime(2018, 9, 1), True), | ||||
|         (offset_nem_sat_aug_4, datetime(2019, 8, 31), True), | ||||
|         (offset_nem_sat_aug_4, datetime(2006, 8, 27), False), | ||||
|         (offset_nem_sat_aug_4, datetime(2007, 8, 28), False), | ||||
|         (offset_nem_sat_aug_4, datetime(2008, 8, 31), False), | ||||
|         (offset_nem_sat_aug_4, datetime(2009, 8, 30), False), | ||||
|         (offset_nem_sat_aug_4, datetime(2010, 8, 29), False), | ||||
|         (offset_nem_sat_aug_4, datetime(2011, 8, 28), False), | ||||
|         (offset_nem_sat_aug_4, datetime(2006, 8, 25), False), | ||||
|         (offset_nem_sat_aug_4, datetime(2007, 8, 24), False), | ||||
|         (offset_nem_sat_aug_4, datetime(2008, 8, 29), False), | ||||
|         (offset_nem_sat_aug_4, datetime(2009, 8, 28), False), | ||||
|         (offset_nem_sat_aug_4, datetime(2010, 8, 27), False), | ||||
|         (offset_nem_sat_aug_4, datetime(2011, 8, 26), False), | ||||
|         (offset_nem_sat_aug_4, datetime(2019, 8, 30), False), | ||||
|         # From Micron, see: | ||||
|         # http://google.brand.edgar-online.com/?sym=MU&formtypeID=7 | ||||
|         (offset_nem_thu_aug_4, datetime(2012, 8, 30), True), | ||||
|         (offset_nem_thu_aug_4, datetime(2011, 9, 1), True), | ||||
|         # See: http://google.brand.edgar-online.com/?sym=MU&formtypeID=13 | ||||
|         (offset_nem_thu_aug_4, datetime(2013, 5, 30), True), | ||||
|         (offset_nem_thu_aug_4, datetime(2013, 2, 28), True), | ||||
|         (offset_nem_thu_aug_4, datetime(2012, 11, 29), True), | ||||
|         (offset_nem_thu_aug_4, datetime(2012, 5, 31), True), | ||||
|         (offset_nem_thu_aug_4, datetime(2007, 3, 1), True), | ||||
|         (offset_nem_thu_aug_4, datetime(1994, 3, 3), True), | ||||
|         (offset_n, datetime(2012, 12, 31), False), | ||||
|         (offset_n, datetime(2013, 1, 1), True), | ||||
|         (offset_n, datetime(2013, 1, 2), False), | ||||
|     ] | ||||
|  | ||||
|     @pytest.mark.parametrize("case", on_offset_cases) | ||||
|     def test_is_on_offset(self, case): | ||||
|         offset, dt, expected = case | ||||
|         assert_is_on_offset(offset, dt, expected) | ||||
|  | ||||
|     def test_offset(self): | ||||
|         offset = makeFY5253NearestEndMonthQuarter( | ||||
|             1, startingMonth=8, weekday=WeekDay.THU, qtr_with_extra_week=4 | ||||
|         ) | ||||
|  | ||||
|         MU = [ | ||||
|             datetime(2012, 5, 31), | ||||
|             datetime(2012, 8, 30), | ||||
|             datetime(2012, 11, 29), | ||||
|             datetime(2013, 2, 28), | ||||
|             datetime(2013, 5, 30), | ||||
|         ] | ||||
|  | ||||
|         date = MU[0] + relativedelta(days=-1) | ||||
|         for expected in MU: | ||||
|             assert_offset_equal(offset, date, expected) | ||||
|             date = date + offset | ||||
|  | ||||
|         assert_offset_equal(offset, datetime(2012, 5, 31), datetime(2012, 8, 30)) | ||||
|         assert_offset_equal(offset, datetime(2012, 5, 30), datetime(2012, 5, 31)) | ||||
|  | ||||
|         offset2 = FY5253Quarter( | ||||
|             weekday=5, startingMonth=12, variation="last", qtr_with_extra_week=4 | ||||
|         ) | ||||
|  | ||||
|         assert_offset_equal(offset2, datetime(2013, 1, 15), datetime(2013, 3, 30)) | ||||
|  | ||||
|  | ||||
| def test_bunched_yearends(): | ||||
|     # GH#14774 cases with two fiscal year-ends in the same calendar-year | ||||
|     fy = FY5253(n=1, weekday=5, startingMonth=12, variation="nearest") | ||||
|     dt = Timestamp("2004-01-01") | ||||
|     assert fy.rollback(dt) == Timestamp("2002-12-28") | ||||
|     assert (-fy)._apply(dt) == Timestamp("2002-12-28") | ||||
|     assert dt - fy == Timestamp("2002-12-28") | ||||
|  | ||||
|     assert fy.rollforward(dt) == Timestamp("2004-01-03") | ||||
|     assert fy._apply(dt) == Timestamp("2004-01-03") | ||||
|     assert fy + dt == Timestamp("2004-01-03") | ||||
|     assert dt + fy == Timestamp("2004-01-03") | ||||
|  | ||||
|     # Same thing, but starting from a Timestamp in the previous year. | ||||
|     dt = Timestamp("2003-12-31") | ||||
|     assert fy.rollback(dt) == Timestamp("2002-12-28") | ||||
|     assert (-fy)._apply(dt) == Timestamp("2002-12-28") | ||||
|     assert dt - fy == Timestamp("2002-12-28") | ||||
|  | ||||
|  | ||||
| def test_fy5253_last_onoffset(): | ||||
|     # GH#18877 dates on the year-end but not normalized to midnight | ||||
|     offset = FY5253(n=-5, startingMonth=5, variation="last", weekday=0) | ||||
|     ts = Timestamp("1984-05-28 06:29:43.955911354+0200", tz="Europe/San_Marino") | ||||
|     fast = offset.is_on_offset(ts) | ||||
|     slow = (ts + offset) - offset == ts | ||||
|     assert fast == slow | ||||
|  | ||||
|  | ||||
| def test_fy5253_nearest_onoffset(): | ||||
|     # GH#18877 dates on the year-end but not normalized to midnight | ||||
|     offset = FY5253(n=3, startingMonth=7, variation="nearest", weekday=2) | ||||
|     ts = Timestamp("2032-07-28 00:12:59.035729419+0000", tz="Africa/Dakar") | ||||
|     fast = offset.is_on_offset(ts) | ||||
|     slow = (ts + offset) - offset == ts | ||||
|     assert fast == slow | ||||
|  | ||||
|  | ||||
| def test_fy5253qtr_onoffset_nearest(): | ||||
|     # GH#19036 | ||||
|     ts = Timestamp("1985-09-02 23:57:46.232550356-0300", tz="Atlantic/Bermuda") | ||||
|     offset = FY5253Quarter( | ||||
|         n=3, qtr_with_extra_week=1, startingMonth=2, variation="nearest", weekday=0 | ||||
|     ) | ||||
|     fast = offset.is_on_offset(ts) | ||||
|     slow = (ts + offset) - offset == ts | ||||
|     assert fast == slow | ||||
|  | ||||
|  | ||||
| def test_fy5253qtr_onoffset_last(): | ||||
|     # GH#19036 | ||||
|     offset = FY5253Quarter( | ||||
|         n=-2, qtr_with_extra_week=1, startingMonth=7, variation="last", weekday=2 | ||||
|     ) | ||||
|     ts = Timestamp("2011-01-26 19:03:40.331096129+0200", tz="Africa/Windhoek") | ||||
|     slow = (ts + offset) - offset == ts | ||||
|     fast = offset.is_on_offset(ts) | ||||
|     assert fast == slow | ||||
| @ -0,0 +1,57 @@ | ||||
| """ | ||||
| Tests for offset behavior with indices. | ||||
| """ | ||||
| import pytest | ||||
|  | ||||
| from pandas import ( | ||||
|     Series, | ||||
|     date_range, | ||||
| ) | ||||
|  | ||||
| from pandas.tseries.offsets import ( | ||||
|     BMonthBegin, | ||||
|     BMonthEnd, | ||||
|     BQuarterBegin, | ||||
|     BQuarterEnd, | ||||
|     BYearBegin, | ||||
|     BYearEnd, | ||||
|     MonthBegin, | ||||
|     MonthEnd, | ||||
|     QuarterBegin, | ||||
|     QuarterEnd, | ||||
|     YearBegin, | ||||
|     YearEnd, | ||||
| ) | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize("n", [-2, 1]) | ||||
| @pytest.mark.parametrize( | ||||
|     "cls", | ||||
|     [ | ||||
|         MonthBegin, | ||||
|         MonthEnd, | ||||
|         BMonthBegin, | ||||
|         BMonthEnd, | ||||
|         QuarterBegin, | ||||
|         QuarterEnd, | ||||
|         BQuarterBegin, | ||||
|         BQuarterEnd, | ||||
|         YearBegin, | ||||
|         YearEnd, | ||||
|         BYearBegin, | ||||
|         BYearEnd, | ||||
|     ], | ||||
| ) | ||||
| def test_apply_index(cls, n): | ||||
|     offset = cls(n=n) | ||||
|     rng = date_range(start="1/1/2000", periods=100000, freq="min") | ||||
|     ser = Series(rng) | ||||
|  | ||||
|     res = rng + offset | ||||
|     assert res.freq is None  # not retained | ||||
|     assert res[0] == rng[0] + offset | ||||
|     assert res[-1] == rng[-1] + offset | ||||
|     res2 = ser + offset | ||||
|     # apply_index is only for indexes, not series, so no res2_v2 | ||||
|     assert res2.iloc[0] == ser.iloc[0] + offset | ||||
|     assert res2.iloc[-1] == ser.iloc[-1] + offset | ||||
| @ -0,0 +1,666 @@ | ||||
| """ | ||||
| Tests for the following offsets: | ||||
| - SemiMonthBegin | ||||
| - SemiMonthEnd | ||||
| - MonthBegin | ||||
| - MonthEnd | ||||
| """ | ||||
| from __future__ import annotations | ||||
|  | ||||
| from datetime import datetime | ||||
|  | ||||
| import pytest | ||||
|  | ||||
| from pandas._libs.tslibs import Timestamp | ||||
| from pandas._libs.tslibs.offsets import ( | ||||
|     MonthBegin, | ||||
|     MonthEnd, | ||||
|     SemiMonthBegin, | ||||
|     SemiMonthEnd, | ||||
| ) | ||||
|  | ||||
| from pandas import ( | ||||
|     DatetimeIndex, | ||||
|     Series, | ||||
|     _testing as tm, | ||||
| ) | ||||
| from pandas.tests.tseries.offsets.common import ( | ||||
|     assert_is_on_offset, | ||||
|     assert_offset_equal, | ||||
| ) | ||||
|  | ||||
|  | ||||
| class TestSemiMonthEnd: | ||||
|     def test_offset_whole_year(self): | ||||
|         dates = ( | ||||
|             datetime(2007, 12, 31), | ||||
|             datetime(2008, 1, 15), | ||||
|             datetime(2008, 1, 31), | ||||
|             datetime(2008, 2, 15), | ||||
|             datetime(2008, 2, 29), | ||||
|             datetime(2008, 3, 15), | ||||
|             datetime(2008, 3, 31), | ||||
|             datetime(2008, 4, 15), | ||||
|             datetime(2008, 4, 30), | ||||
|             datetime(2008, 5, 15), | ||||
|             datetime(2008, 5, 31), | ||||
|             datetime(2008, 6, 15), | ||||
|             datetime(2008, 6, 30), | ||||
|             datetime(2008, 7, 15), | ||||
|             datetime(2008, 7, 31), | ||||
|             datetime(2008, 8, 15), | ||||
|             datetime(2008, 8, 31), | ||||
|             datetime(2008, 9, 15), | ||||
|             datetime(2008, 9, 30), | ||||
|             datetime(2008, 10, 15), | ||||
|             datetime(2008, 10, 31), | ||||
|             datetime(2008, 11, 15), | ||||
|             datetime(2008, 11, 30), | ||||
|             datetime(2008, 12, 15), | ||||
|             datetime(2008, 12, 31), | ||||
|         ) | ||||
|  | ||||
|         for base, exp_date in zip(dates[:-1], dates[1:]): | ||||
|             assert_offset_equal(SemiMonthEnd(), base, exp_date) | ||||
|  | ||||
|         # ensure .apply_index works as expected | ||||
|         shift = DatetimeIndex(dates[:-1]) | ||||
|         with tm.assert_produces_warning(None): | ||||
|             # GH#22535 check that we don't get a FutureWarning from adding | ||||
|             # an integer array to PeriodIndex | ||||
|             result = SemiMonthEnd() + shift | ||||
|  | ||||
|         exp = DatetimeIndex(dates[1:]) | ||||
|         tm.assert_index_equal(result, exp) | ||||
|  | ||||
|     offset_cases = [] | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             SemiMonthEnd(), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 15), | ||||
|                 datetime(2008, 1, 15): datetime(2008, 1, 31), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 2, 15), | ||||
|                 datetime(2006, 12, 14): datetime(2006, 12, 15), | ||||
|                 datetime(2006, 12, 29): datetime(2006, 12, 31), | ||||
|                 datetime(2006, 12, 31): datetime(2007, 1, 15), | ||||
|                 datetime(2007, 1, 1): datetime(2007, 1, 15), | ||||
|                 datetime(2006, 12, 1): datetime(2006, 12, 15), | ||||
|                 datetime(2006, 12, 15): datetime(2006, 12, 31), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             SemiMonthEnd(day_of_month=20), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 20), | ||||
|                 datetime(2008, 1, 15): datetime(2008, 1, 20), | ||||
|                 datetime(2008, 1, 21): datetime(2008, 1, 31), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 2, 20), | ||||
|                 datetime(2006, 12, 14): datetime(2006, 12, 20), | ||||
|                 datetime(2006, 12, 29): datetime(2006, 12, 31), | ||||
|                 datetime(2006, 12, 31): datetime(2007, 1, 20), | ||||
|                 datetime(2007, 1, 1): datetime(2007, 1, 20), | ||||
|                 datetime(2006, 12, 1): datetime(2006, 12, 20), | ||||
|                 datetime(2006, 12, 15): datetime(2006, 12, 20), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             SemiMonthEnd(0), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 15), | ||||
|                 datetime(2008, 1, 16): datetime(2008, 1, 31), | ||||
|                 datetime(2008, 1, 15): datetime(2008, 1, 15), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 1, 31), | ||||
|                 datetime(2006, 12, 29): datetime(2006, 12, 31), | ||||
|                 datetime(2006, 12, 31): datetime(2006, 12, 31), | ||||
|                 datetime(2007, 1, 1): datetime(2007, 1, 15), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             SemiMonthEnd(0, day_of_month=16), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 16), | ||||
|                 datetime(2008, 1, 16): datetime(2008, 1, 16), | ||||
|                 datetime(2008, 1, 15): datetime(2008, 1, 16), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 1, 31), | ||||
|                 datetime(2006, 12, 29): datetime(2006, 12, 31), | ||||
|                 datetime(2006, 12, 31): datetime(2006, 12, 31), | ||||
|                 datetime(2007, 1, 1): datetime(2007, 1, 16), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             SemiMonthEnd(2), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 31), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 2, 29), | ||||
|                 datetime(2006, 12, 29): datetime(2007, 1, 15), | ||||
|                 datetime(2006, 12, 31): datetime(2007, 1, 31), | ||||
|                 datetime(2007, 1, 1): datetime(2007, 1, 31), | ||||
|                 datetime(2007, 1, 16): datetime(2007, 2, 15), | ||||
|                 datetime(2006, 11, 1): datetime(2006, 11, 30), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             SemiMonthEnd(-1), | ||||
|             { | ||||
|                 datetime(2007, 1, 1): datetime(2006, 12, 31), | ||||
|                 datetime(2008, 6, 30): datetime(2008, 6, 15), | ||||
|                 datetime(2008, 12, 31): datetime(2008, 12, 15), | ||||
|                 datetime(2006, 12, 29): datetime(2006, 12, 15), | ||||
|                 datetime(2006, 12, 30): datetime(2006, 12, 15), | ||||
|                 datetime(2007, 1, 1): datetime(2006, 12, 31), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             SemiMonthEnd(-1, day_of_month=4), | ||||
|             { | ||||
|                 datetime(2007, 1, 1): datetime(2006, 12, 31), | ||||
|                 datetime(2007, 1, 4): datetime(2006, 12, 31), | ||||
|                 datetime(2008, 6, 30): datetime(2008, 6, 4), | ||||
|                 datetime(2008, 12, 31): datetime(2008, 12, 4), | ||||
|                 datetime(2006, 12, 5): datetime(2006, 12, 4), | ||||
|                 datetime(2006, 12, 30): datetime(2006, 12, 4), | ||||
|                 datetime(2007, 1, 1): datetime(2006, 12, 31), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             SemiMonthEnd(-2), | ||||
|             { | ||||
|                 datetime(2007, 1, 1): datetime(2006, 12, 15), | ||||
|                 datetime(2008, 6, 30): datetime(2008, 5, 31), | ||||
|                 datetime(2008, 3, 15): datetime(2008, 2, 15), | ||||
|                 datetime(2008, 12, 31): datetime(2008, 11, 30), | ||||
|                 datetime(2006, 12, 29): datetime(2006, 11, 30), | ||||
|                 datetime(2006, 12, 14): datetime(2006, 11, 15), | ||||
|                 datetime(2007, 1, 1): datetime(2006, 12, 15), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     @pytest.mark.parametrize("case", offset_cases) | ||||
|     def test_offset(self, case): | ||||
|         offset, cases = case | ||||
|         for base, expected in cases.items(): | ||||
|             assert_offset_equal(offset, base, expected) | ||||
|  | ||||
|     @pytest.mark.parametrize("case", offset_cases) | ||||
|     def test_apply_index(self, case): | ||||
|         # https://github.com/pandas-dev/pandas/issues/34580 | ||||
|         offset, cases = case | ||||
|         shift = DatetimeIndex(cases.keys()) | ||||
|         exp = DatetimeIndex(cases.values()) | ||||
|  | ||||
|         with tm.assert_produces_warning(None): | ||||
|             # GH#22535 check that we don't get a FutureWarning from adding | ||||
|             # an integer array to PeriodIndex | ||||
|             result = offset + shift | ||||
|         tm.assert_index_equal(result, exp) | ||||
|  | ||||
|     on_offset_cases = [ | ||||
|         (datetime(2007, 12, 31), True), | ||||
|         (datetime(2007, 12, 15), True), | ||||
|         (datetime(2007, 12, 14), False), | ||||
|         (datetime(2007, 12, 1), False), | ||||
|         (datetime(2008, 2, 29), True), | ||||
|     ] | ||||
|  | ||||
|     @pytest.mark.parametrize("case", on_offset_cases) | ||||
|     def test_is_on_offset(self, case): | ||||
|         dt, expected = case | ||||
|         assert_is_on_offset(SemiMonthEnd(), dt, expected) | ||||
|  | ||||
|     @pytest.mark.parametrize("klass", [Series, DatetimeIndex]) | ||||
|     def test_vectorized_offset_addition(self, klass): | ||||
|         shift = klass( | ||||
|             [ | ||||
|                 Timestamp("2000-01-15 00:15:00", tz="US/Central"), | ||||
|                 Timestamp("2000-02-15", tz="US/Central"), | ||||
|             ], | ||||
|             name="a", | ||||
|         ) | ||||
|  | ||||
|         with tm.assert_produces_warning(None): | ||||
|             # GH#22535 check that we don't get a FutureWarning from adding | ||||
|             # an integer array to PeriodIndex | ||||
|             result = shift + SemiMonthEnd() | ||||
|             result2 = SemiMonthEnd() + shift | ||||
|  | ||||
|         exp = klass( | ||||
|             [ | ||||
|                 Timestamp("2000-01-31 00:15:00", tz="US/Central"), | ||||
|                 Timestamp("2000-02-29", tz="US/Central"), | ||||
|             ], | ||||
|             name="a", | ||||
|         ) | ||||
|         tm.assert_equal(result, exp) | ||||
|         tm.assert_equal(result2, exp) | ||||
|  | ||||
|         shift = klass( | ||||
|             [ | ||||
|                 Timestamp("2000-01-01 00:15:00", tz="US/Central"), | ||||
|                 Timestamp("2000-02-01", tz="US/Central"), | ||||
|             ], | ||||
|             name="a", | ||||
|         ) | ||||
|  | ||||
|         with tm.assert_produces_warning(None): | ||||
|             # GH#22535 check that we don't get a FutureWarning from adding | ||||
|             # an integer array to PeriodIndex | ||||
|             result = shift + SemiMonthEnd() | ||||
|             result2 = SemiMonthEnd() + shift | ||||
|  | ||||
|         exp = klass( | ||||
|             [ | ||||
|                 Timestamp("2000-01-15 00:15:00", tz="US/Central"), | ||||
|                 Timestamp("2000-02-15", tz="US/Central"), | ||||
|             ], | ||||
|             name="a", | ||||
|         ) | ||||
|         tm.assert_equal(result, exp) | ||||
|         tm.assert_equal(result2, exp) | ||||
|  | ||||
|  | ||||
| class TestSemiMonthBegin: | ||||
|     def test_offset_whole_year(self): | ||||
|         dates = ( | ||||
|             datetime(2007, 12, 15), | ||||
|             datetime(2008, 1, 1), | ||||
|             datetime(2008, 1, 15), | ||||
|             datetime(2008, 2, 1), | ||||
|             datetime(2008, 2, 15), | ||||
|             datetime(2008, 3, 1), | ||||
|             datetime(2008, 3, 15), | ||||
|             datetime(2008, 4, 1), | ||||
|             datetime(2008, 4, 15), | ||||
|             datetime(2008, 5, 1), | ||||
|             datetime(2008, 5, 15), | ||||
|             datetime(2008, 6, 1), | ||||
|             datetime(2008, 6, 15), | ||||
|             datetime(2008, 7, 1), | ||||
|             datetime(2008, 7, 15), | ||||
|             datetime(2008, 8, 1), | ||||
|             datetime(2008, 8, 15), | ||||
|             datetime(2008, 9, 1), | ||||
|             datetime(2008, 9, 15), | ||||
|             datetime(2008, 10, 1), | ||||
|             datetime(2008, 10, 15), | ||||
|             datetime(2008, 11, 1), | ||||
|             datetime(2008, 11, 15), | ||||
|             datetime(2008, 12, 1), | ||||
|             datetime(2008, 12, 15), | ||||
|         ) | ||||
|  | ||||
|         for base, exp_date in zip(dates[:-1], dates[1:]): | ||||
|             assert_offset_equal(SemiMonthBegin(), base, exp_date) | ||||
|  | ||||
|         # ensure .apply_index works as expected | ||||
|         shift = DatetimeIndex(dates[:-1]) | ||||
|         with tm.assert_produces_warning(None): | ||||
|             # GH#22535 check that we don't get a FutureWarning from adding | ||||
|             # an integer array to PeriodIndex | ||||
|             result = SemiMonthBegin() + shift | ||||
|  | ||||
|         exp = DatetimeIndex(dates[1:]) | ||||
|         tm.assert_index_equal(result, exp) | ||||
|  | ||||
|     offset_cases = [ | ||||
|         ( | ||||
|             SemiMonthBegin(), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 15), | ||||
|                 datetime(2008, 1, 15): datetime(2008, 2, 1), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 2, 1), | ||||
|                 datetime(2006, 12, 14): datetime(2006, 12, 15), | ||||
|                 datetime(2006, 12, 29): datetime(2007, 1, 1), | ||||
|                 datetime(2006, 12, 31): datetime(2007, 1, 1), | ||||
|                 datetime(2007, 1, 1): datetime(2007, 1, 15), | ||||
|                 datetime(2006, 12, 1): datetime(2006, 12, 15), | ||||
|                 datetime(2006, 12, 15): datetime(2007, 1, 1), | ||||
|             }, | ||||
|         ), | ||||
|         ( | ||||
|             SemiMonthBegin(day_of_month=20), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 20), | ||||
|                 datetime(2008, 1, 15): datetime(2008, 1, 20), | ||||
|                 datetime(2008, 1, 21): datetime(2008, 2, 1), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 2, 1), | ||||
|                 datetime(2006, 12, 14): datetime(2006, 12, 20), | ||||
|                 datetime(2006, 12, 29): datetime(2007, 1, 1), | ||||
|                 datetime(2006, 12, 31): datetime(2007, 1, 1), | ||||
|                 datetime(2007, 1, 1): datetime(2007, 1, 20), | ||||
|                 datetime(2006, 12, 1): datetime(2006, 12, 20), | ||||
|                 datetime(2006, 12, 15): datetime(2006, 12, 20), | ||||
|             }, | ||||
|         ), | ||||
|         ( | ||||
|             SemiMonthBegin(0), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 1), | ||||
|                 datetime(2008, 1, 16): datetime(2008, 2, 1), | ||||
|                 datetime(2008, 1, 15): datetime(2008, 1, 15), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 2, 1), | ||||
|                 datetime(2006, 12, 29): datetime(2007, 1, 1), | ||||
|                 datetime(2006, 12, 2): datetime(2006, 12, 15), | ||||
|                 datetime(2007, 1, 1): datetime(2007, 1, 1), | ||||
|             }, | ||||
|         ), | ||||
|         ( | ||||
|             SemiMonthBegin(0, day_of_month=16), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 1), | ||||
|                 datetime(2008, 1, 16): datetime(2008, 1, 16), | ||||
|                 datetime(2008, 1, 15): datetime(2008, 1, 16), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 2, 1), | ||||
|                 datetime(2006, 12, 29): datetime(2007, 1, 1), | ||||
|                 datetime(2006, 12, 31): datetime(2007, 1, 1), | ||||
|                 datetime(2007, 1, 5): datetime(2007, 1, 16), | ||||
|                 datetime(2007, 1, 1): datetime(2007, 1, 1), | ||||
|             }, | ||||
|         ), | ||||
|         ( | ||||
|             SemiMonthBegin(2), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 2, 1), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 2, 15), | ||||
|                 datetime(2006, 12, 1): datetime(2007, 1, 1), | ||||
|                 datetime(2006, 12, 29): datetime(2007, 1, 15), | ||||
|                 datetime(2006, 12, 15): datetime(2007, 1, 15), | ||||
|                 datetime(2007, 1, 1): datetime(2007, 2, 1), | ||||
|                 datetime(2007, 1, 16): datetime(2007, 2, 15), | ||||
|                 datetime(2006, 11, 1): datetime(2006, 12, 1), | ||||
|             }, | ||||
|         ), | ||||
|         ( | ||||
|             SemiMonthBegin(-1), | ||||
|             { | ||||
|                 datetime(2007, 1, 1): datetime(2006, 12, 15), | ||||
|                 datetime(2008, 6, 30): datetime(2008, 6, 15), | ||||
|                 datetime(2008, 6, 14): datetime(2008, 6, 1), | ||||
|                 datetime(2008, 12, 31): datetime(2008, 12, 15), | ||||
|                 datetime(2006, 12, 29): datetime(2006, 12, 15), | ||||
|                 datetime(2006, 12, 15): datetime(2006, 12, 1), | ||||
|                 datetime(2007, 1, 1): datetime(2006, 12, 15), | ||||
|             }, | ||||
|         ), | ||||
|         ( | ||||
|             SemiMonthBegin(-1, day_of_month=4), | ||||
|             { | ||||
|                 datetime(2007, 1, 1): datetime(2006, 12, 4), | ||||
|                 datetime(2007, 1, 4): datetime(2007, 1, 1), | ||||
|                 datetime(2008, 6, 30): datetime(2008, 6, 4), | ||||
|                 datetime(2008, 12, 31): datetime(2008, 12, 4), | ||||
|                 datetime(2006, 12, 5): datetime(2006, 12, 4), | ||||
|                 datetime(2006, 12, 30): datetime(2006, 12, 4), | ||||
|                 datetime(2006, 12, 2): datetime(2006, 12, 1), | ||||
|                 datetime(2007, 1, 1): datetime(2006, 12, 4), | ||||
|             }, | ||||
|         ), | ||||
|         ( | ||||
|             SemiMonthBegin(-2), | ||||
|             { | ||||
|                 datetime(2007, 1, 1): datetime(2006, 12, 1), | ||||
|                 datetime(2008, 6, 30): datetime(2008, 6, 1), | ||||
|                 datetime(2008, 6, 14): datetime(2008, 5, 15), | ||||
|                 datetime(2008, 12, 31): datetime(2008, 12, 1), | ||||
|                 datetime(2006, 12, 29): datetime(2006, 12, 1), | ||||
|                 datetime(2006, 12, 15): datetime(2006, 11, 15), | ||||
|                 datetime(2007, 1, 1): datetime(2006, 12, 1), | ||||
|             }, | ||||
|         ), | ||||
|     ] | ||||
|  | ||||
|     @pytest.mark.parametrize("case", offset_cases) | ||||
|     def test_offset(self, case): | ||||
|         offset, cases = case | ||||
|         for base, expected in cases.items(): | ||||
|             assert_offset_equal(offset, base, expected) | ||||
|  | ||||
|     @pytest.mark.parametrize("case", offset_cases) | ||||
|     def test_apply_index(self, case): | ||||
|         offset, cases = case | ||||
|         shift = DatetimeIndex(cases.keys()) | ||||
|  | ||||
|         with tm.assert_produces_warning(None): | ||||
|             # GH#22535 check that we don't get a FutureWarning from adding | ||||
|             # an integer array to PeriodIndex | ||||
|             result = offset + shift | ||||
|  | ||||
|         exp = DatetimeIndex(cases.values()) | ||||
|         tm.assert_index_equal(result, exp) | ||||
|  | ||||
|     on_offset_cases = [ | ||||
|         (datetime(2007, 12, 1), True), | ||||
|         (datetime(2007, 12, 15), True), | ||||
|         (datetime(2007, 12, 14), False), | ||||
|         (datetime(2007, 12, 31), False), | ||||
|         (datetime(2008, 2, 15), True), | ||||
|     ] | ||||
|  | ||||
|     @pytest.mark.parametrize("case", on_offset_cases) | ||||
|     def test_is_on_offset(self, case): | ||||
|         dt, expected = case | ||||
|         assert_is_on_offset(SemiMonthBegin(), dt, expected) | ||||
|  | ||||
|     @pytest.mark.parametrize("klass", [Series, DatetimeIndex]) | ||||
|     def test_vectorized_offset_addition(self, klass): | ||||
|         shift = klass( | ||||
|             [ | ||||
|                 Timestamp("2000-01-15 00:15:00", tz="US/Central"), | ||||
|                 Timestamp("2000-02-15", tz="US/Central"), | ||||
|             ], | ||||
|             name="a", | ||||
|         ) | ||||
|         with tm.assert_produces_warning(None): | ||||
|             # GH#22535 check that we don't get a FutureWarning from adding | ||||
|             # an integer array to PeriodIndex | ||||
|             result = shift + SemiMonthBegin() | ||||
|             result2 = SemiMonthBegin() + shift | ||||
|  | ||||
|         exp = klass( | ||||
|             [ | ||||
|                 Timestamp("2000-02-01 00:15:00", tz="US/Central"), | ||||
|                 Timestamp("2000-03-01", tz="US/Central"), | ||||
|             ], | ||||
|             name="a", | ||||
|         ) | ||||
|         tm.assert_equal(result, exp) | ||||
|         tm.assert_equal(result2, exp) | ||||
|  | ||||
|         shift = klass( | ||||
|             [ | ||||
|                 Timestamp("2000-01-01 00:15:00", tz="US/Central"), | ||||
|                 Timestamp("2000-02-01", tz="US/Central"), | ||||
|             ], | ||||
|             name="a", | ||||
|         ) | ||||
|         with tm.assert_produces_warning(None): | ||||
|             # GH#22535 check that we don't get a FutureWarning from adding | ||||
|             # an integer array to PeriodIndex | ||||
|             result = shift + SemiMonthBegin() | ||||
|             result2 = SemiMonthBegin() + shift | ||||
|  | ||||
|         exp = klass( | ||||
|             [ | ||||
|                 Timestamp("2000-01-15 00:15:00", tz="US/Central"), | ||||
|                 Timestamp("2000-02-15", tz="US/Central"), | ||||
|             ], | ||||
|             name="a", | ||||
|         ) | ||||
|         tm.assert_equal(result, exp) | ||||
|         tm.assert_equal(result2, exp) | ||||
|  | ||||
|  | ||||
| class TestMonthBegin: | ||||
|     offset_cases = [] | ||||
|     # NOTE: I'm not entirely happy with the logic here for Begin -ss | ||||
|     # see thread 'offset conventions' on the ML | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             MonthBegin(), | ||||
|             { | ||||
|                 datetime(2008, 1, 31): datetime(2008, 2, 1), | ||||
|                 datetime(2008, 2, 1): datetime(2008, 3, 1), | ||||
|                 datetime(2006, 12, 31): datetime(2007, 1, 1), | ||||
|                 datetime(2006, 12, 1): datetime(2007, 1, 1), | ||||
|                 datetime(2007, 1, 31): datetime(2007, 2, 1), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             MonthBegin(0), | ||||
|             { | ||||
|                 datetime(2008, 1, 31): datetime(2008, 2, 1), | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 1), | ||||
|                 datetime(2006, 12, 3): datetime(2007, 1, 1), | ||||
|                 datetime(2007, 1, 31): datetime(2007, 2, 1), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             MonthBegin(2), | ||||
|             { | ||||
|                 datetime(2008, 2, 29): datetime(2008, 4, 1), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 3, 1), | ||||
|                 datetime(2006, 12, 31): datetime(2007, 2, 1), | ||||
|                 datetime(2007, 12, 28): datetime(2008, 2, 1), | ||||
|                 datetime(2007, 1, 1): datetime(2007, 3, 1), | ||||
|                 datetime(2006, 11, 1): datetime(2007, 1, 1), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             MonthBegin(-1), | ||||
|             { | ||||
|                 datetime(2007, 1, 1): datetime(2006, 12, 1), | ||||
|                 datetime(2008, 5, 31): datetime(2008, 5, 1), | ||||
|                 datetime(2008, 12, 31): datetime(2008, 12, 1), | ||||
|                 datetime(2006, 12, 29): datetime(2006, 12, 1), | ||||
|                 datetime(2006, 1, 2): datetime(2006, 1, 1), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     @pytest.mark.parametrize("case", offset_cases) | ||||
|     def test_offset(self, case): | ||||
|         offset, cases = case | ||||
|         for base, expected in cases.items(): | ||||
|             assert_offset_equal(offset, base, expected) | ||||
|  | ||||
|  | ||||
| class TestMonthEnd: | ||||
|     def test_day_of_month(self): | ||||
|         dt = datetime(2007, 1, 1) | ||||
|         offset = MonthEnd() | ||||
|  | ||||
|         result = dt + offset | ||||
|         assert result == Timestamp(2007, 1, 31) | ||||
|  | ||||
|         result = result + offset | ||||
|         assert result == Timestamp(2007, 2, 28) | ||||
|  | ||||
|     def test_normalize(self): | ||||
|         dt = datetime(2007, 1, 1, 3) | ||||
|  | ||||
|         result = dt + MonthEnd(normalize=True) | ||||
|         expected = dt.replace(hour=0) + MonthEnd() | ||||
|         assert result == expected | ||||
|  | ||||
|     offset_cases = [] | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             MonthEnd(), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 31), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 2, 29), | ||||
|                 datetime(2006, 12, 29): datetime(2006, 12, 31), | ||||
|                 datetime(2006, 12, 31): datetime(2007, 1, 31), | ||||
|                 datetime(2007, 1, 1): datetime(2007, 1, 31), | ||||
|                 datetime(2006, 12, 1): datetime(2006, 12, 31), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             MonthEnd(0), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 31), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 1, 31), | ||||
|                 datetime(2006, 12, 29): datetime(2006, 12, 31), | ||||
|                 datetime(2006, 12, 31): datetime(2006, 12, 31), | ||||
|                 datetime(2007, 1, 1): datetime(2007, 1, 31), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             MonthEnd(2), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 2, 29), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 3, 31), | ||||
|                 datetime(2006, 12, 29): datetime(2007, 1, 31), | ||||
|                 datetime(2006, 12, 31): datetime(2007, 2, 28), | ||||
|                 datetime(2007, 1, 1): datetime(2007, 2, 28), | ||||
|                 datetime(2006, 11, 1): datetime(2006, 12, 31), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             MonthEnd(-1), | ||||
|             { | ||||
|                 datetime(2007, 1, 1): datetime(2006, 12, 31), | ||||
|                 datetime(2008, 6, 30): datetime(2008, 5, 31), | ||||
|                 datetime(2008, 12, 31): datetime(2008, 11, 30), | ||||
|                 datetime(2006, 12, 29): datetime(2006, 11, 30), | ||||
|                 datetime(2006, 12, 30): datetime(2006, 11, 30), | ||||
|                 datetime(2007, 1, 1): datetime(2006, 12, 31), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     @pytest.mark.parametrize("case", offset_cases) | ||||
|     def test_offset(self, case): | ||||
|         offset, cases = case | ||||
|         for base, expected in cases.items(): | ||||
|             assert_offset_equal(offset, base, expected) | ||||
|  | ||||
|     on_offset_cases = [ | ||||
|         (MonthEnd(), datetime(2007, 12, 31), True), | ||||
|         (MonthEnd(), datetime(2008, 1, 1), False), | ||||
|     ] | ||||
|  | ||||
|     @pytest.mark.parametrize("case", on_offset_cases) | ||||
|     def test_is_on_offset(self, case): | ||||
|         offset, dt, expected = case | ||||
|         assert_is_on_offset(offset, dt, expected) | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -0,0 +1,60 @@ | ||||
| """ | ||||
| Behavioral based tests for offsets and date_range. | ||||
|  | ||||
| This file is adapted from https://github.com/pandas-dev/pandas/pull/18761 - | ||||
| which was more ambitious but less idiomatic in its use of Hypothesis. | ||||
|  | ||||
| You may wish to consult the previous version for inspiration on further | ||||
| tests, or when trying to pin down the bugs exposed by the tests below. | ||||
| """ | ||||
| from hypothesis import ( | ||||
|     assume, | ||||
|     given, | ||||
| ) | ||||
| import pytest | ||||
| import pytz | ||||
|  | ||||
| import pandas as pd | ||||
| from pandas._testing._hypothesis import ( | ||||
|     DATETIME_JAN_1_1900_OPTIONAL_TZ, | ||||
|     YQM_OFFSET, | ||||
| ) | ||||
|  | ||||
| # ---------------------------------------------------------------- | ||||
| # Offset-specific behaviour tests | ||||
|  | ||||
|  | ||||
| @pytest.mark.arm_slow | ||||
| @given(DATETIME_JAN_1_1900_OPTIONAL_TZ, YQM_OFFSET) | ||||
| def test_on_offset_implementations(dt, offset): | ||||
|     assume(not offset.normalize) | ||||
|     # check that the class-specific implementations of is_on_offset match | ||||
|     # the general case definition: | ||||
|     #   (dt + offset) - offset == dt | ||||
|     try: | ||||
|         compare = (dt + offset) - offset | ||||
|     except (pytz.NonExistentTimeError, pytz.AmbiguousTimeError): | ||||
|         # When dt + offset does not exist or is DST-ambiguous, assume(False) to | ||||
|         # indicate to hypothesis that this is not a valid test case | ||||
|         # DST-ambiguous example (GH41906): | ||||
|         # dt = datetime.datetime(1900, 1, 1, tzinfo=pytz.timezone('Africa/Kinshasa')) | ||||
|         # offset = MonthBegin(66) | ||||
|         assume(False) | ||||
|  | ||||
|     assert offset.is_on_offset(dt) == (compare == dt) | ||||
|  | ||||
|  | ||||
| @given(YQM_OFFSET) | ||||
| def test_shift_across_dst(offset): | ||||
|     # GH#18319 check that 1) timezone is correctly normalized and | ||||
|     # 2) that hour is not incorrectly changed by this normalization | ||||
|     assume(not offset.normalize) | ||||
|  | ||||
|     # Note that dti includes a transition across DST boundary | ||||
|     dti = pd.date_range( | ||||
|         start="2017-10-30 12:00:00", end="2017-11-06", freq="D", tz="US/Eastern" | ||||
|     ) | ||||
|     assert (dti.hour == 12).all()  # we haven't screwed up yet | ||||
|  | ||||
|     res = dti + offset | ||||
|     assert (res.hour == 12).all() | ||||
| @ -0,0 +1,303 @@ | ||||
| """ | ||||
| Tests for the following offsets: | ||||
| - QuarterBegin | ||||
| - QuarterEnd | ||||
| """ | ||||
| from __future__ import annotations | ||||
|  | ||||
| from datetime import datetime | ||||
|  | ||||
| import pytest | ||||
|  | ||||
| import pandas._testing as tm | ||||
| from pandas.tests.tseries.offsets.common import ( | ||||
|     assert_is_on_offset, | ||||
|     assert_offset_equal, | ||||
| ) | ||||
|  | ||||
| from pandas.tseries.offsets import ( | ||||
|     QuarterBegin, | ||||
|     QuarterEnd, | ||||
| ) | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize("klass", (QuarterBegin, QuarterEnd)) | ||||
| def test_quarterly_dont_normalize(klass): | ||||
|     date = datetime(2012, 3, 31, 5, 30) | ||||
|     result = date + klass() | ||||
|     assert result.time() == date.time() | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize("offset", [QuarterBegin(), QuarterEnd()]) | ||||
| @pytest.mark.parametrize( | ||||
|     "date", | ||||
|     [ | ||||
|         datetime(2016, m, d) | ||||
|         for m in [10, 11, 12] | ||||
|         for d in [1, 2, 3, 28, 29, 30, 31] | ||||
|         if not (m == 11 and d == 31) | ||||
|     ], | ||||
| ) | ||||
| def test_on_offset(offset, date): | ||||
|     res = offset.is_on_offset(date) | ||||
|     slow_version = date == (date + offset) - offset | ||||
|     assert res == slow_version | ||||
|  | ||||
|  | ||||
| class TestQuarterBegin: | ||||
|     def test_repr(self): | ||||
|         expected = "<QuarterBegin: startingMonth=3>" | ||||
|         assert repr(QuarterBegin()) == expected | ||||
|         expected = "<QuarterBegin: startingMonth=3>" | ||||
|         assert repr(QuarterBegin(startingMonth=3)) == expected | ||||
|         expected = "<QuarterBegin: startingMonth=1>" | ||||
|         assert repr(QuarterBegin(startingMonth=1)) == expected | ||||
|  | ||||
|     def test_is_anchored(self): | ||||
|         msg = "QuarterBegin.is_anchored is deprecated " | ||||
|  | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             assert QuarterBegin(startingMonth=1).is_anchored() | ||||
|             assert QuarterBegin().is_anchored() | ||||
|             assert not QuarterBegin(2, startingMonth=1).is_anchored() | ||||
|  | ||||
|     def test_offset_corner_case(self): | ||||
|         # corner | ||||
|         offset = QuarterBegin(n=-1, startingMonth=1) | ||||
|         assert datetime(2010, 2, 1) + offset == datetime(2010, 1, 1) | ||||
|  | ||||
|     offset_cases = [] | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             QuarterBegin(startingMonth=1), | ||||
|             { | ||||
|                 datetime(2007, 12, 1): datetime(2008, 1, 1), | ||||
|                 datetime(2008, 1, 1): datetime(2008, 4, 1), | ||||
|                 datetime(2008, 2, 15): datetime(2008, 4, 1), | ||||
|                 datetime(2008, 2, 29): datetime(2008, 4, 1), | ||||
|                 datetime(2008, 3, 15): datetime(2008, 4, 1), | ||||
|                 datetime(2008, 3, 31): datetime(2008, 4, 1), | ||||
|                 datetime(2008, 4, 15): datetime(2008, 7, 1), | ||||
|                 datetime(2008, 4, 1): datetime(2008, 7, 1), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             QuarterBegin(startingMonth=2), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 2, 1), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 2, 1), | ||||
|                 datetime(2008, 1, 15): datetime(2008, 2, 1), | ||||
|                 datetime(2008, 2, 29): datetime(2008, 5, 1), | ||||
|                 datetime(2008, 3, 15): datetime(2008, 5, 1), | ||||
|                 datetime(2008, 3, 31): datetime(2008, 5, 1), | ||||
|                 datetime(2008, 4, 15): datetime(2008, 5, 1), | ||||
|                 datetime(2008, 4, 30): datetime(2008, 5, 1), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             QuarterBegin(startingMonth=1, n=0), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 1), | ||||
|                 datetime(2008, 12, 1): datetime(2009, 1, 1), | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 1), | ||||
|                 datetime(2008, 2, 15): datetime(2008, 4, 1), | ||||
|                 datetime(2008, 2, 29): datetime(2008, 4, 1), | ||||
|                 datetime(2008, 3, 15): datetime(2008, 4, 1), | ||||
|                 datetime(2008, 3, 31): datetime(2008, 4, 1), | ||||
|                 datetime(2008, 4, 15): datetime(2008, 7, 1), | ||||
|                 datetime(2008, 4, 30): datetime(2008, 7, 1), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             QuarterBegin(startingMonth=1, n=-1), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2007, 10, 1), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 1, 1), | ||||
|                 datetime(2008, 2, 15): datetime(2008, 1, 1), | ||||
|                 datetime(2008, 2, 29): datetime(2008, 1, 1), | ||||
|                 datetime(2008, 3, 15): datetime(2008, 1, 1), | ||||
|                 datetime(2008, 3, 31): datetime(2008, 1, 1), | ||||
|                 datetime(2008, 4, 15): datetime(2008, 4, 1), | ||||
|                 datetime(2008, 4, 30): datetime(2008, 4, 1), | ||||
|                 datetime(2008, 7, 1): datetime(2008, 4, 1), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             QuarterBegin(startingMonth=1, n=2), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 7, 1), | ||||
|                 datetime(2008, 2, 15): datetime(2008, 7, 1), | ||||
|                 datetime(2008, 2, 29): datetime(2008, 7, 1), | ||||
|                 datetime(2008, 3, 15): datetime(2008, 7, 1), | ||||
|                 datetime(2008, 3, 31): datetime(2008, 7, 1), | ||||
|                 datetime(2008, 4, 15): datetime(2008, 10, 1), | ||||
|                 datetime(2008, 4, 1): datetime(2008, 10, 1), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     @pytest.mark.parametrize("case", offset_cases) | ||||
|     def test_offset(self, case): | ||||
|         offset, cases = case | ||||
|         for base, expected in cases.items(): | ||||
|             assert_offset_equal(offset, base, expected) | ||||
|  | ||||
|  | ||||
| class TestQuarterEnd: | ||||
|     def test_repr(self): | ||||
|         expected = "<QuarterEnd: startingMonth=3>" | ||||
|         assert repr(QuarterEnd()) == expected | ||||
|         expected = "<QuarterEnd: startingMonth=3>" | ||||
|         assert repr(QuarterEnd(startingMonth=3)) == expected | ||||
|         expected = "<QuarterEnd: startingMonth=1>" | ||||
|         assert repr(QuarterEnd(startingMonth=1)) == expected | ||||
|  | ||||
|     def test_is_anchored(self): | ||||
|         msg = "QuarterEnd.is_anchored is deprecated " | ||||
|  | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             assert QuarterEnd(startingMonth=1).is_anchored() | ||||
|             assert QuarterEnd().is_anchored() | ||||
|             assert not QuarterEnd(2, startingMonth=1).is_anchored() | ||||
|  | ||||
|     def test_offset_corner_case(self): | ||||
|         # corner | ||||
|         offset = QuarterEnd(n=-1, startingMonth=1) | ||||
|         assert datetime(2010, 2, 1) + offset == datetime(2010, 1, 31) | ||||
|  | ||||
|     offset_cases = [] | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             QuarterEnd(startingMonth=1), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 31), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 4, 30), | ||||
|                 datetime(2008, 2, 15): datetime(2008, 4, 30), | ||||
|                 datetime(2008, 2, 29): datetime(2008, 4, 30), | ||||
|                 datetime(2008, 3, 15): datetime(2008, 4, 30), | ||||
|                 datetime(2008, 3, 31): datetime(2008, 4, 30), | ||||
|                 datetime(2008, 4, 15): datetime(2008, 4, 30), | ||||
|                 datetime(2008, 4, 30): datetime(2008, 7, 31), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             QuarterEnd(startingMonth=2), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 2, 29), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 2, 29), | ||||
|                 datetime(2008, 2, 15): datetime(2008, 2, 29), | ||||
|                 datetime(2008, 2, 29): datetime(2008, 5, 31), | ||||
|                 datetime(2008, 3, 15): datetime(2008, 5, 31), | ||||
|                 datetime(2008, 3, 31): datetime(2008, 5, 31), | ||||
|                 datetime(2008, 4, 15): datetime(2008, 5, 31), | ||||
|                 datetime(2008, 4, 30): datetime(2008, 5, 31), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             QuarterEnd(startingMonth=1, n=0), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 31), | ||||
|                 datetime(2008, 1, 31): datetime(2008, 1, 31), | ||||
|                 datetime(2008, 2, 15): datetime(2008, 4, 30), | ||||
|                 datetime(2008, 2, 29): datetime(2008, 4, 30), | ||||
|                 datetime(2008, 3, 15): datetime(2008, 4, 30), | ||||
|                 datetime(2008, 3, 31): datetime(2008, 4, 30), | ||||
|                 datetime(2008, 4, 15): datetime(2008, 4, 30), | ||||
|                 datetime(2008, 4, 30): datetime(2008, 4, 30), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             QuarterEnd(startingMonth=1, n=-1), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2007, 10, 31), | ||||
|                 datetime(2008, 1, 31): datetime(2007, 10, 31), | ||||
|                 datetime(2008, 2, 15): datetime(2008, 1, 31), | ||||
|                 datetime(2008, 2, 29): datetime(2008, 1, 31), | ||||
|                 datetime(2008, 3, 15): datetime(2008, 1, 31), | ||||
|                 datetime(2008, 3, 31): datetime(2008, 1, 31), | ||||
|                 datetime(2008, 4, 15): datetime(2008, 1, 31), | ||||
|                 datetime(2008, 4, 30): datetime(2008, 1, 31), | ||||
|                 datetime(2008, 7, 1): datetime(2008, 4, 30), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             QuarterEnd(startingMonth=1, n=2), | ||||
|             { | ||||
|                 datetime(2008, 1, 31): datetime(2008, 7, 31), | ||||
|                 datetime(2008, 2, 15): datetime(2008, 7, 31), | ||||
|                 datetime(2008, 2, 29): datetime(2008, 7, 31), | ||||
|                 datetime(2008, 3, 15): datetime(2008, 7, 31), | ||||
|                 datetime(2008, 3, 31): datetime(2008, 7, 31), | ||||
|                 datetime(2008, 4, 15): datetime(2008, 7, 31), | ||||
|                 datetime(2008, 4, 30): datetime(2008, 10, 31), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     @pytest.mark.parametrize("case", offset_cases) | ||||
|     def test_offset(self, case): | ||||
|         offset, cases = case | ||||
|         for base, expected in cases.items(): | ||||
|             assert_offset_equal(offset, base, expected) | ||||
|  | ||||
|     on_offset_cases = [ | ||||
|         (QuarterEnd(1, startingMonth=1), datetime(2008, 1, 31), True), | ||||
|         (QuarterEnd(1, startingMonth=1), datetime(2007, 12, 31), False), | ||||
|         (QuarterEnd(1, startingMonth=1), datetime(2008, 2, 29), False), | ||||
|         (QuarterEnd(1, startingMonth=1), datetime(2007, 3, 30), False), | ||||
|         (QuarterEnd(1, startingMonth=1), datetime(2007, 3, 31), False), | ||||
|         (QuarterEnd(1, startingMonth=1), datetime(2008, 4, 30), True), | ||||
|         (QuarterEnd(1, startingMonth=1), datetime(2008, 5, 30), False), | ||||
|         (QuarterEnd(1, startingMonth=1), datetime(2008, 5, 31), False), | ||||
|         (QuarterEnd(1, startingMonth=1), datetime(2007, 6, 29), False), | ||||
|         (QuarterEnd(1, startingMonth=1), datetime(2007, 6, 30), False), | ||||
|         (QuarterEnd(1, startingMonth=2), datetime(2008, 1, 31), False), | ||||
|         (QuarterEnd(1, startingMonth=2), datetime(2007, 12, 31), False), | ||||
|         (QuarterEnd(1, startingMonth=2), datetime(2008, 2, 29), True), | ||||
|         (QuarterEnd(1, startingMonth=2), datetime(2007, 3, 30), False), | ||||
|         (QuarterEnd(1, startingMonth=2), datetime(2007, 3, 31), False), | ||||
|         (QuarterEnd(1, startingMonth=2), datetime(2008, 4, 30), False), | ||||
|         (QuarterEnd(1, startingMonth=2), datetime(2008, 5, 30), False), | ||||
|         (QuarterEnd(1, startingMonth=2), datetime(2008, 5, 31), True), | ||||
|         (QuarterEnd(1, startingMonth=2), datetime(2007, 6, 29), False), | ||||
|         (QuarterEnd(1, startingMonth=2), datetime(2007, 6, 30), False), | ||||
|         (QuarterEnd(1, startingMonth=3), datetime(2008, 1, 31), False), | ||||
|         (QuarterEnd(1, startingMonth=3), datetime(2007, 12, 31), True), | ||||
|         (QuarterEnd(1, startingMonth=3), datetime(2008, 2, 29), False), | ||||
|         (QuarterEnd(1, startingMonth=3), datetime(2007, 3, 30), False), | ||||
|         (QuarterEnd(1, startingMonth=3), datetime(2007, 3, 31), True), | ||||
|         (QuarterEnd(1, startingMonth=3), datetime(2008, 4, 30), False), | ||||
|         (QuarterEnd(1, startingMonth=3), datetime(2008, 5, 30), False), | ||||
|         (QuarterEnd(1, startingMonth=3), datetime(2008, 5, 31), False), | ||||
|         (QuarterEnd(1, startingMonth=3), datetime(2007, 6, 29), False), | ||||
|         (QuarterEnd(1, startingMonth=3), datetime(2007, 6, 30), True), | ||||
|     ] | ||||
|  | ||||
|     @pytest.mark.parametrize("case", on_offset_cases) | ||||
|     def test_is_on_offset(self, case): | ||||
|         offset, dt, expected = case | ||||
|         assert_is_on_offset(offset, dt, expected) | ||||
| @ -0,0 +1,405 @@ | ||||
| """ | ||||
| Tests for offsets.Tick and subclasses | ||||
| """ | ||||
| from datetime import ( | ||||
|     datetime, | ||||
|     timedelta, | ||||
| ) | ||||
|  | ||||
| from hypothesis import ( | ||||
|     assume, | ||||
|     example, | ||||
|     given, | ||||
| ) | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas._libs.tslibs.offsets import delta_to_tick | ||||
| from pandas.errors import OutOfBoundsTimedelta | ||||
|  | ||||
| from pandas import ( | ||||
|     Timedelta, | ||||
|     Timestamp, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
| from pandas._testing._hypothesis import INT_NEG_999_TO_POS_999 | ||||
| from pandas.tests.tseries.offsets.common import assert_offset_equal | ||||
|  | ||||
| from pandas.tseries import offsets | ||||
| from pandas.tseries.offsets import ( | ||||
|     Hour, | ||||
|     Micro, | ||||
|     Milli, | ||||
|     Minute, | ||||
|     Nano, | ||||
|     Second, | ||||
| ) | ||||
|  | ||||
| # --------------------------------------------------------------------- | ||||
| # Test Helpers | ||||
|  | ||||
| tick_classes = [Hour, Minute, Second, Milli, Micro, Nano] | ||||
|  | ||||
|  | ||||
| # --------------------------------------------------------------------- | ||||
|  | ||||
|  | ||||
| def test_apply_ticks(): | ||||
|     result = offsets.Hour(3) + offsets.Hour(4) | ||||
|     exp = offsets.Hour(7) | ||||
|     assert result == exp | ||||
|  | ||||
|  | ||||
| def test_delta_to_tick(): | ||||
|     delta = timedelta(3) | ||||
|  | ||||
|     tick = delta_to_tick(delta) | ||||
|     assert tick == offsets.Day(3) | ||||
|  | ||||
|     td = Timedelta(nanoseconds=5) | ||||
|     tick = delta_to_tick(td) | ||||
|     assert tick == Nano(5) | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize("cls", tick_classes) | ||||
| @example(n=2, m=3) | ||||
| @example(n=800, m=300) | ||||
| @example(n=1000, m=5) | ||||
| @given(n=INT_NEG_999_TO_POS_999, m=INT_NEG_999_TO_POS_999) | ||||
| def test_tick_add_sub(cls, n, m): | ||||
|     # For all Tick subclasses and all integers n, m, we should have | ||||
|     # tick(n) + tick(m) == tick(n+m) | ||||
|     # tick(n) - tick(m) == tick(n-m) | ||||
|     left = cls(n) | ||||
|     right = cls(m) | ||||
|     expected = cls(n + m) | ||||
|  | ||||
|     assert left + right == expected | ||||
|  | ||||
|     expected = cls(n - m) | ||||
|     assert left - right == expected | ||||
|  | ||||
|  | ||||
| @pytest.mark.arm_slow | ||||
| @pytest.mark.parametrize("cls", tick_classes) | ||||
| @example(n=2, m=3) | ||||
| @given(n=INT_NEG_999_TO_POS_999, m=INT_NEG_999_TO_POS_999) | ||||
| def test_tick_equality(cls, n, m): | ||||
|     assume(m != n) | ||||
|     # tick == tock iff tick.n == tock.n | ||||
|     left = cls(n) | ||||
|     right = cls(m) | ||||
|     assert left != right | ||||
|  | ||||
|     right = cls(n) | ||||
|     assert left == right | ||||
|     assert not left != right | ||||
|  | ||||
|     if n != 0: | ||||
|         assert cls(n) != cls(-n) | ||||
|  | ||||
|  | ||||
| # --------------------------------------------------------------------- | ||||
|  | ||||
|  | ||||
| def test_Hour(): | ||||
|     assert_offset_equal(Hour(), datetime(2010, 1, 1), datetime(2010, 1, 1, 1)) | ||||
|     assert_offset_equal(Hour(-1), datetime(2010, 1, 1, 1), datetime(2010, 1, 1)) | ||||
|     assert_offset_equal(2 * Hour(), datetime(2010, 1, 1), datetime(2010, 1, 1, 2)) | ||||
|     assert_offset_equal(-1 * Hour(), datetime(2010, 1, 1, 1), datetime(2010, 1, 1)) | ||||
|  | ||||
|     assert Hour(3) + Hour(2) == Hour(5) | ||||
|     assert Hour(3) - Hour(2) == Hour() | ||||
|  | ||||
|     assert Hour(4) != Hour(1) | ||||
|  | ||||
|  | ||||
| def test_Minute(): | ||||
|     assert_offset_equal(Minute(), datetime(2010, 1, 1), datetime(2010, 1, 1, 0, 1)) | ||||
|     assert_offset_equal(Minute(-1), datetime(2010, 1, 1, 0, 1), datetime(2010, 1, 1)) | ||||
|     assert_offset_equal(2 * Minute(), datetime(2010, 1, 1), datetime(2010, 1, 1, 0, 2)) | ||||
|     assert_offset_equal(-1 * Minute(), datetime(2010, 1, 1, 0, 1), datetime(2010, 1, 1)) | ||||
|  | ||||
|     assert Minute(3) + Minute(2) == Minute(5) | ||||
|     assert Minute(3) - Minute(2) == Minute() | ||||
|     assert Minute(5) != Minute() | ||||
|  | ||||
|  | ||||
| def test_Second(): | ||||
|     assert_offset_equal(Second(), datetime(2010, 1, 1), datetime(2010, 1, 1, 0, 0, 1)) | ||||
|     assert_offset_equal(Second(-1), datetime(2010, 1, 1, 0, 0, 1), datetime(2010, 1, 1)) | ||||
|     assert_offset_equal( | ||||
|         2 * Second(), datetime(2010, 1, 1), datetime(2010, 1, 1, 0, 0, 2) | ||||
|     ) | ||||
|     assert_offset_equal( | ||||
|         -1 * Second(), datetime(2010, 1, 1, 0, 0, 1), datetime(2010, 1, 1) | ||||
|     ) | ||||
|  | ||||
|     assert Second(3) + Second(2) == Second(5) | ||||
|     assert Second(3) - Second(2) == Second() | ||||
|  | ||||
|  | ||||
| def test_Millisecond(): | ||||
|     assert_offset_equal( | ||||
|         Milli(), datetime(2010, 1, 1), datetime(2010, 1, 1, 0, 0, 0, 1000) | ||||
|     ) | ||||
|     assert_offset_equal( | ||||
|         Milli(-1), datetime(2010, 1, 1, 0, 0, 0, 1000), datetime(2010, 1, 1) | ||||
|     ) | ||||
|     assert_offset_equal( | ||||
|         Milli(2), datetime(2010, 1, 1), datetime(2010, 1, 1, 0, 0, 0, 2000) | ||||
|     ) | ||||
|     assert_offset_equal( | ||||
|         2 * Milli(), datetime(2010, 1, 1), datetime(2010, 1, 1, 0, 0, 0, 2000) | ||||
|     ) | ||||
|     assert_offset_equal( | ||||
|         -1 * Milli(), datetime(2010, 1, 1, 0, 0, 0, 1000), datetime(2010, 1, 1) | ||||
|     ) | ||||
|  | ||||
|     assert Milli(3) + Milli(2) == Milli(5) | ||||
|     assert Milli(3) - Milli(2) == Milli() | ||||
|  | ||||
|  | ||||
| def test_MillisecondTimestampArithmetic(): | ||||
|     assert_offset_equal( | ||||
|         Milli(), Timestamp("2010-01-01"), Timestamp("2010-01-01 00:00:00.001") | ||||
|     ) | ||||
|     assert_offset_equal( | ||||
|         Milli(-1), Timestamp("2010-01-01 00:00:00.001"), Timestamp("2010-01-01") | ||||
|     ) | ||||
|  | ||||
|  | ||||
| def test_Microsecond(): | ||||
|     assert_offset_equal(Micro(), datetime(2010, 1, 1), datetime(2010, 1, 1, 0, 0, 0, 1)) | ||||
|     assert_offset_equal( | ||||
|         Micro(-1), datetime(2010, 1, 1, 0, 0, 0, 1), datetime(2010, 1, 1) | ||||
|     ) | ||||
|  | ||||
|     assert_offset_equal( | ||||
|         2 * Micro(), datetime(2010, 1, 1), datetime(2010, 1, 1, 0, 0, 0, 2) | ||||
|     ) | ||||
|     assert_offset_equal( | ||||
|         -1 * Micro(), datetime(2010, 1, 1, 0, 0, 0, 1), datetime(2010, 1, 1) | ||||
|     ) | ||||
|  | ||||
|     assert Micro(3) + Micro(2) == Micro(5) | ||||
|     assert Micro(3) - Micro(2) == Micro() | ||||
|  | ||||
|  | ||||
| def test_NanosecondGeneric(): | ||||
|     timestamp = Timestamp(datetime(2010, 1, 1)) | ||||
|     assert timestamp.nanosecond == 0 | ||||
|  | ||||
|     result = timestamp + Nano(10) | ||||
|     assert result.nanosecond == 10 | ||||
|  | ||||
|     reverse_result = Nano(10) + timestamp | ||||
|     assert reverse_result.nanosecond == 10 | ||||
|  | ||||
|  | ||||
| def test_Nanosecond(): | ||||
|     timestamp = Timestamp(datetime(2010, 1, 1)) | ||||
|     assert_offset_equal(Nano(), timestamp, timestamp + np.timedelta64(1, "ns")) | ||||
|     assert_offset_equal(Nano(-1), timestamp + np.timedelta64(1, "ns"), timestamp) | ||||
|     assert_offset_equal(2 * Nano(), timestamp, timestamp + np.timedelta64(2, "ns")) | ||||
|     assert_offset_equal(-1 * Nano(), timestamp + np.timedelta64(1, "ns"), timestamp) | ||||
|  | ||||
|     assert Nano(3) + Nano(2) == Nano(5) | ||||
|     assert Nano(3) - Nano(2) == Nano() | ||||
|  | ||||
|     # GH9284 | ||||
|     assert Nano(1) + Nano(10) == Nano(11) | ||||
|     assert Nano(5) + Micro(1) == Nano(1005) | ||||
|     assert Micro(5) + Nano(1) == Nano(5001) | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize( | ||||
|     "kls, expected", | ||||
|     [ | ||||
|         (Hour, Timedelta(hours=5)), | ||||
|         (Minute, Timedelta(hours=2, minutes=3)), | ||||
|         (Second, Timedelta(hours=2, seconds=3)), | ||||
|         (Milli, Timedelta(hours=2, milliseconds=3)), | ||||
|         (Micro, Timedelta(hours=2, microseconds=3)), | ||||
|         (Nano, Timedelta(hours=2, nanoseconds=3)), | ||||
|     ], | ||||
| ) | ||||
| def test_tick_addition(kls, expected): | ||||
|     offset = kls(3) | ||||
|     td = Timedelta(hours=2) | ||||
|  | ||||
|     for other in [td, td.to_pytimedelta(), td.to_timedelta64()]: | ||||
|         result = offset + other | ||||
|         assert isinstance(result, Timedelta) | ||||
|         assert result == expected | ||||
|  | ||||
|         result = other + offset | ||||
|         assert isinstance(result, Timedelta) | ||||
|         assert result == expected | ||||
|  | ||||
|  | ||||
| def test_tick_delta_overflow(): | ||||
|     # GH#55503 raise OutOfBoundsTimedelta, not OverflowError | ||||
|     tick = offsets.Day(10**9) | ||||
|     msg = "Cannot cast 1000000000 days 00:00:00 to unit='ns' without overflow" | ||||
|     depr_msg = "Day.delta is deprecated" | ||||
|     with pytest.raises(OutOfBoundsTimedelta, match=msg): | ||||
|         with tm.assert_produces_warning(FutureWarning, match=depr_msg): | ||||
|             tick.delta | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize("cls", tick_classes) | ||||
| def test_tick_division(cls): | ||||
|     off = cls(10) | ||||
|  | ||||
|     assert off / cls(5) == 2 | ||||
|     assert off / 2 == cls(5) | ||||
|     assert off / 2.0 == cls(5) | ||||
|  | ||||
|     assert off / off._as_pd_timedelta == 1 | ||||
|     assert off / off._as_pd_timedelta.to_timedelta64() == 1 | ||||
|  | ||||
|     assert off / Nano(1) == off._as_pd_timedelta / Nano(1)._as_pd_timedelta | ||||
|  | ||||
|     if cls is not Nano: | ||||
|         # A case where we end up with a smaller class | ||||
|         result = off / 1000 | ||||
|         assert isinstance(result, offsets.Tick) | ||||
|         assert not isinstance(result, cls) | ||||
|         assert result._as_pd_timedelta == off._as_pd_timedelta / 1000 | ||||
|  | ||||
|     if cls._nanos_inc < Timedelta(seconds=1)._value: | ||||
|         # Case where we end up with a bigger class | ||||
|         result = off / 0.001 | ||||
|         assert isinstance(result, offsets.Tick) | ||||
|         assert not isinstance(result, cls) | ||||
|         assert result._as_pd_timedelta == off._as_pd_timedelta / 0.001 | ||||
|  | ||||
|  | ||||
| def test_tick_mul_float(): | ||||
|     off = Micro(2) | ||||
|  | ||||
|     # Case where we retain type | ||||
|     result = off * 1.5 | ||||
|     expected = Micro(3) | ||||
|     assert result == expected | ||||
|     assert isinstance(result, Micro) | ||||
|  | ||||
|     # Case where we bump up to the next type | ||||
|     result = off * 1.25 | ||||
|     expected = Nano(2500) | ||||
|     assert result == expected | ||||
|     assert isinstance(result, Nano) | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize("cls", tick_classes) | ||||
| def test_tick_rdiv(cls): | ||||
|     off = cls(10) | ||||
|     delta = off._as_pd_timedelta | ||||
|     td64 = delta.to_timedelta64() | ||||
|     instance__type = ".".join([cls.__module__, cls.__name__]) | ||||
|     msg = ( | ||||
|         "unsupported operand type\\(s\\) for \\/: 'int'|'float' and " | ||||
|         f"'{instance__type}'" | ||||
|     ) | ||||
|  | ||||
|     with pytest.raises(TypeError, match=msg): | ||||
|         2 / off | ||||
|     with pytest.raises(TypeError, match=msg): | ||||
|         2.0 / off | ||||
|  | ||||
|     assert (td64 * 2.5) / off == 2.5 | ||||
|  | ||||
|     if cls is not Nano: | ||||
|         # skip pytimedelta for Nano since it gets dropped | ||||
|         assert (delta.to_pytimedelta() * 2) / off == 2 | ||||
|  | ||||
|     result = np.array([2 * td64, td64]) / off | ||||
|     expected = np.array([2.0, 1.0]) | ||||
|     tm.assert_numpy_array_equal(result, expected) | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize("cls1", tick_classes) | ||||
| @pytest.mark.parametrize("cls2", tick_classes) | ||||
| def test_tick_zero(cls1, cls2): | ||||
|     assert cls1(0) == cls2(0) | ||||
|     assert cls1(0) + cls2(0) == cls1(0) | ||||
|  | ||||
|     if cls1 is not Nano: | ||||
|         assert cls1(2) + cls2(0) == cls1(2) | ||||
|  | ||||
|     if cls1 is Nano: | ||||
|         assert cls1(2) + Nano(0) == cls1(2) | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize("cls", tick_classes) | ||||
| def test_tick_equalities(cls): | ||||
|     assert cls() == cls(1) | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize("cls", tick_classes) | ||||
| def test_tick_offset(cls): | ||||
|     msg = f"{cls.__name__}.is_anchored is deprecated " | ||||
|  | ||||
|     with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|         assert not cls().is_anchored() | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize("cls", tick_classes) | ||||
| def test_compare_ticks(cls): | ||||
|     three = cls(3) | ||||
|     four = cls(4) | ||||
|  | ||||
|     assert three < cls(4) | ||||
|     assert cls(3) < four | ||||
|     assert four > cls(3) | ||||
|     assert cls(4) > three | ||||
|     assert cls(3) == cls(3) | ||||
|     assert cls(3) != cls(4) | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize("cls", tick_classes) | ||||
| def test_compare_ticks_to_strs(cls): | ||||
|     # GH#23524 | ||||
|     off = cls(19) | ||||
|  | ||||
|     # These tests should work with any strings, but we particularly are | ||||
|     #  interested in "infer" as that comparison is convenient to make in | ||||
|     #  Datetime/Timedelta Array/Index constructors | ||||
|     assert not off == "infer" | ||||
|     assert not "foo" == off | ||||
|  | ||||
|     instance_type = ".".join([cls.__module__, cls.__name__]) | ||||
|     msg = ( | ||||
|         "'<'|'<='|'>'|'>=' not supported between instances of " | ||||
|         f"'str' and '{instance_type}'|'{instance_type}' and 'str'" | ||||
|     ) | ||||
|  | ||||
|     for left, right in [("infer", off), (off, "infer")]: | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             left < right | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             left <= right | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             left > right | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             left >= right | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize("cls", tick_classes) | ||||
| def test_compare_ticks_to_timedeltalike(cls): | ||||
|     off = cls(19) | ||||
|  | ||||
|     td = off._as_pd_timedelta | ||||
|  | ||||
|     others = [td, td.to_timedelta64()] | ||||
|     if cls is not Nano: | ||||
|         others.append(td.to_pytimedelta()) | ||||
|  | ||||
|     for other in others: | ||||
|         assert off == other | ||||
|         assert not off != other | ||||
|         assert not off < other | ||||
|         assert not off > other | ||||
|         assert off <= other | ||||
|         assert off >= other | ||||
| @ -0,0 +1,351 @@ | ||||
| """ | ||||
| Tests for the following offsets: | ||||
| - Week | ||||
| - WeekOfMonth | ||||
| - LastWeekOfMonth | ||||
| """ | ||||
| from __future__ import annotations | ||||
|  | ||||
| from datetime import ( | ||||
|     datetime, | ||||
|     timedelta, | ||||
| ) | ||||
|  | ||||
| import pytest | ||||
|  | ||||
| from pandas._libs.tslibs import Timestamp | ||||
| from pandas._libs.tslibs.offsets import ( | ||||
|     Day, | ||||
|     LastWeekOfMonth, | ||||
|     Week, | ||||
|     WeekOfMonth, | ||||
| ) | ||||
|  | ||||
| import pandas._testing as tm | ||||
| from pandas.tests.tseries.offsets.common import ( | ||||
|     WeekDay, | ||||
|     assert_is_on_offset, | ||||
|     assert_offset_equal, | ||||
| ) | ||||
|  | ||||
|  | ||||
| class TestWeek: | ||||
|     def test_repr(self): | ||||
|         assert repr(Week(weekday=0)) == "<Week: weekday=0>" | ||||
|         assert repr(Week(n=-1, weekday=0)) == "<-1 * Week: weekday=0>" | ||||
|         assert repr(Week(n=-2, weekday=0)) == "<-2 * Weeks: weekday=0>" | ||||
|  | ||||
|     def test_corner(self): | ||||
|         with pytest.raises(ValueError, match="Day must be"): | ||||
|             Week(weekday=7) | ||||
|  | ||||
|         with pytest.raises(ValueError, match="Day must be"): | ||||
|             Week(weekday=-1) | ||||
|  | ||||
|     def test_is_anchored(self): | ||||
|         msg = "Week.is_anchored is deprecated " | ||||
|  | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             assert Week(weekday=0).is_anchored() | ||||
|             assert not Week().is_anchored() | ||||
|             assert not Week(2, weekday=2).is_anchored() | ||||
|             assert not Week(2).is_anchored() | ||||
|  | ||||
|     offset_cases = [] | ||||
|     # not business week | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             Week(), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 8), | ||||
|                 datetime(2008, 1, 4): datetime(2008, 1, 11), | ||||
|                 datetime(2008, 1, 5): datetime(2008, 1, 12), | ||||
|                 datetime(2008, 1, 6): datetime(2008, 1, 13), | ||||
|                 datetime(2008, 1, 7): datetime(2008, 1, 14), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     # Mon | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             Week(weekday=0), | ||||
|             { | ||||
|                 datetime(2007, 12, 31): datetime(2008, 1, 7), | ||||
|                 datetime(2008, 1, 4): datetime(2008, 1, 7), | ||||
|                 datetime(2008, 1, 5): datetime(2008, 1, 7), | ||||
|                 datetime(2008, 1, 6): datetime(2008, 1, 7), | ||||
|                 datetime(2008, 1, 7): datetime(2008, 1, 14), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     # n=0 -> roll forward. Mon | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             Week(0, weekday=0), | ||||
|             { | ||||
|                 datetime(2007, 12, 31): datetime(2007, 12, 31), | ||||
|                 datetime(2008, 1, 4): datetime(2008, 1, 7), | ||||
|                 datetime(2008, 1, 5): datetime(2008, 1, 7), | ||||
|                 datetime(2008, 1, 6): datetime(2008, 1, 7), | ||||
|                 datetime(2008, 1, 7): datetime(2008, 1, 7), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     # n=0 -> roll forward. Mon | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             Week(-2, weekday=1), | ||||
|             { | ||||
|                 datetime(2010, 4, 6): datetime(2010, 3, 23), | ||||
|                 datetime(2010, 4, 8): datetime(2010, 3, 30), | ||||
|                 datetime(2010, 4, 5): datetime(2010, 3, 23), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     @pytest.mark.parametrize("case", offset_cases) | ||||
|     def test_offset(self, case): | ||||
|         offset, cases = case | ||||
|         for base, expected in cases.items(): | ||||
|             assert_offset_equal(offset, base, expected) | ||||
|  | ||||
|     @pytest.mark.parametrize("weekday", range(7)) | ||||
|     def test_is_on_offset(self, weekday): | ||||
|         offset = Week(weekday=weekday) | ||||
|  | ||||
|         for day in range(1, 8): | ||||
|             date = datetime(2008, 1, day) | ||||
|             expected = day % 7 == weekday | ||||
|         assert_is_on_offset(offset, date, expected) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "n,date", | ||||
|         [ | ||||
|             (2, "1862-01-13 09:03:34.873477378+0210"), | ||||
|             (-2, "1856-10-24 16:18:36.556360110-0717"), | ||||
|         ], | ||||
|     ) | ||||
|     def test_is_on_offset_weekday_none(self, n, date): | ||||
|         # GH 18510 Week with weekday = None, normalize = False | ||||
|         # should always be is_on_offset | ||||
|         offset = Week(n=n, weekday=None) | ||||
|         ts = Timestamp(date, tz="Africa/Lusaka") | ||||
|         fast = offset.is_on_offset(ts) | ||||
|         slow = (ts + offset) - offset == ts | ||||
|         assert fast == slow | ||||
|  | ||||
|     def test_week_add_invalid(self): | ||||
|         # Week with weekday should raise TypeError and _not_ AttributeError | ||||
|         #  when adding invalid offset | ||||
|         offset = Week(weekday=1) | ||||
|         other = Day() | ||||
|         with pytest.raises(TypeError, match="Cannot add"): | ||||
|             offset + other | ||||
|  | ||||
|  | ||||
| class TestWeekOfMonth: | ||||
|     def test_constructor(self): | ||||
|         with pytest.raises(ValueError, match="^Week"): | ||||
|             WeekOfMonth(n=1, week=4, weekday=0) | ||||
|  | ||||
|         with pytest.raises(ValueError, match="^Week"): | ||||
|             WeekOfMonth(n=1, week=-1, weekday=0) | ||||
|  | ||||
|         with pytest.raises(ValueError, match="^Day"): | ||||
|             WeekOfMonth(n=1, week=0, weekday=-1) | ||||
|  | ||||
|         with pytest.raises(ValueError, match="^Day"): | ||||
|             WeekOfMonth(n=1, week=0, weekday=-7) | ||||
|  | ||||
|     def test_repr(self): | ||||
|         assert ( | ||||
|             repr(WeekOfMonth(weekday=1, week=2)) == "<WeekOfMonth: week=2, weekday=1>" | ||||
|         ) | ||||
|  | ||||
|     def test_offset(self): | ||||
|         date1 = datetime(2011, 1, 4)  # 1st Tuesday of Month | ||||
|         date2 = datetime(2011, 1, 11)  # 2nd Tuesday of Month | ||||
|         date3 = datetime(2011, 1, 18)  # 3rd Tuesday of Month | ||||
|         date4 = datetime(2011, 1, 25)  # 4th Tuesday of Month | ||||
|  | ||||
|         # see for loop for structure | ||||
|         test_cases = [ | ||||
|             (-2, 2, 1, date1, datetime(2010, 11, 16)), | ||||
|             (-2, 2, 1, date2, datetime(2010, 11, 16)), | ||||
|             (-2, 2, 1, date3, datetime(2010, 11, 16)), | ||||
|             (-2, 2, 1, date4, datetime(2010, 12, 21)), | ||||
|             (-1, 2, 1, date1, datetime(2010, 12, 21)), | ||||
|             (-1, 2, 1, date2, datetime(2010, 12, 21)), | ||||
|             (-1, 2, 1, date3, datetime(2010, 12, 21)), | ||||
|             (-1, 2, 1, date4, datetime(2011, 1, 18)), | ||||
|             (0, 0, 1, date1, datetime(2011, 1, 4)), | ||||
|             (0, 0, 1, date2, datetime(2011, 2, 1)), | ||||
|             (0, 0, 1, date3, datetime(2011, 2, 1)), | ||||
|             (0, 0, 1, date4, datetime(2011, 2, 1)), | ||||
|             (0, 1, 1, date1, datetime(2011, 1, 11)), | ||||
|             (0, 1, 1, date2, datetime(2011, 1, 11)), | ||||
|             (0, 1, 1, date3, datetime(2011, 2, 8)), | ||||
|             (0, 1, 1, date4, datetime(2011, 2, 8)), | ||||
|             (0, 0, 1, date1, datetime(2011, 1, 4)), | ||||
|             (0, 1, 1, date2, datetime(2011, 1, 11)), | ||||
|             (0, 2, 1, date3, datetime(2011, 1, 18)), | ||||
|             (0, 3, 1, date4, datetime(2011, 1, 25)), | ||||
|             (1, 0, 0, date1, datetime(2011, 2, 7)), | ||||
|             (1, 0, 0, date2, datetime(2011, 2, 7)), | ||||
|             (1, 0, 0, date3, datetime(2011, 2, 7)), | ||||
|             (1, 0, 0, date4, datetime(2011, 2, 7)), | ||||
|             (1, 0, 1, date1, datetime(2011, 2, 1)), | ||||
|             (1, 0, 1, date2, datetime(2011, 2, 1)), | ||||
|             (1, 0, 1, date3, datetime(2011, 2, 1)), | ||||
|             (1, 0, 1, date4, datetime(2011, 2, 1)), | ||||
|             (1, 0, 2, date1, datetime(2011, 1, 5)), | ||||
|             (1, 0, 2, date2, datetime(2011, 2, 2)), | ||||
|             (1, 0, 2, date3, datetime(2011, 2, 2)), | ||||
|             (1, 0, 2, date4, datetime(2011, 2, 2)), | ||||
|             (1, 2, 1, date1, datetime(2011, 1, 18)), | ||||
|             (1, 2, 1, date2, datetime(2011, 1, 18)), | ||||
|             (1, 2, 1, date3, datetime(2011, 2, 15)), | ||||
|             (1, 2, 1, date4, datetime(2011, 2, 15)), | ||||
|             (2, 2, 1, date1, datetime(2011, 2, 15)), | ||||
|             (2, 2, 1, date2, datetime(2011, 2, 15)), | ||||
|             (2, 2, 1, date3, datetime(2011, 3, 15)), | ||||
|             (2, 2, 1, date4, datetime(2011, 3, 15)), | ||||
|         ] | ||||
|  | ||||
|         for n, week, weekday, dt, expected in test_cases: | ||||
|             offset = WeekOfMonth(n, week=week, weekday=weekday) | ||||
|             assert_offset_equal(offset, dt, expected) | ||||
|  | ||||
|         # try subtracting | ||||
|         result = datetime(2011, 2, 1) - WeekOfMonth(week=1, weekday=2) | ||||
|         assert result == datetime(2011, 1, 12) | ||||
|  | ||||
|         result = datetime(2011, 2, 3) - WeekOfMonth(week=0, weekday=2) | ||||
|         assert result == datetime(2011, 2, 2) | ||||
|  | ||||
|     on_offset_cases = [ | ||||
|         (0, 0, datetime(2011, 2, 7), True), | ||||
|         (0, 0, datetime(2011, 2, 6), False), | ||||
|         (0, 0, datetime(2011, 2, 14), False), | ||||
|         (1, 0, datetime(2011, 2, 14), True), | ||||
|         (0, 1, datetime(2011, 2, 1), True), | ||||
|         (0, 1, datetime(2011, 2, 8), False), | ||||
|     ] | ||||
|  | ||||
|     @pytest.mark.parametrize("case", on_offset_cases) | ||||
|     def test_is_on_offset(self, case): | ||||
|         week, weekday, dt, expected = case | ||||
|         offset = WeekOfMonth(week=week, weekday=weekday) | ||||
|         assert offset.is_on_offset(dt) == expected | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "n,week,date,tz", | ||||
|         [ | ||||
|             (2, 2, "1916-05-15 01:14:49.583410462+0422", "Asia/Qyzylorda"), | ||||
|             (-3, 1, "1980-12-08 03:38:52.878321185+0500", "Asia/Oral"), | ||||
|         ], | ||||
|     ) | ||||
|     def test_is_on_offset_nanoseconds(self, n, week, date, tz): | ||||
|         # GH 18864 | ||||
|         # Make sure that nanoseconds don't trip up is_on_offset (and with it apply) | ||||
|         offset = WeekOfMonth(n=n, week=week, weekday=0) | ||||
|         ts = Timestamp(date, tz=tz) | ||||
|         fast = offset.is_on_offset(ts) | ||||
|         slow = (ts + offset) - offset == ts | ||||
|         assert fast == slow | ||||
|  | ||||
|  | ||||
| class TestLastWeekOfMonth: | ||||
|     def test_constructor(self): | ||||
|         with pytest.raises(ValueError, match="^N cannot be 0"): | ||||
|             LastWeekOfMonth(n=0, weekday=1) | ||||
|  | ||||
|         with pytest.raises(ValueError, match="^Day"): | ||||
|             LastWeekOfMonth(n=1, weekday=-1) | ||||
|  | ||||
|         with pytest.raises(ValueError, match="^Day"): | ||||
|             LastWeekOfMonth(n=1, weekday=7) | ||||
|  | ||||
|     def test_offset(self): | ||||
|         # Saturday | ||||
|         last_sat = datetime(2013, 8, 31) | ||||
|         next_sat = datetime(2013, 9, 28) | ||||
|         offset_sat = LastWeekOfMonth(n=1, weekday=5) | ||||
|  | ||||
|         one_day_before = last_sat + timedelta(days=-1) | ||||
|         assert one_day_before + offset_sat == last_sat | ||||
|  | ||||
|         one_day_after = last_sat + timedelta(days=+1) | ||||
|         assert one_day_after + offset_sat == next_sat | ||||
|  | ||||
|         # Test On that day | ||||
|         assert last_sat + offset_sat == next_sat | ||||
|  | ||||
|         # Thursday | ||||
|  | ||||
|         offset_thur = LastWeekOfMonth(n=1, weekday=3) | ||||
|         last_thurs = datetime(2013, 1, 31) | ||||
|         next_thurs = datetime(2013, 2, 28) | ||||
|  | ||||
|         one_day_before = last_thurs + timedelta(days=-1) | ||||
|         assert one_day_before + offset_thur == last_thurs | ||||
|  | ||||
|         one_day_after = last_thurs + timedelta(days=+1) | ||||
|         assert one_day_after + offset_thur == next_thurs | ||||
|  | ||||
|         # Test on that day | ||||
|         assert last_thurs + offset_thur == next_thurs | ||||
|  | ||||
|         three_before = last_thurs + timedelta(days=-3) | ||||
|         assert three_before + offset_thur == last_thurs | ||||
|  | ||||
|         two_after = last_thurs + timedelta(days=+2) | ||||
|         assert two_after + offset_thur == next_thurs | ||||
|  | ||||
|         offset_sunday = LastWeekOfMonth(n=1, weekday=WeekDay.SUN) | ||||
|         assert datetime(2013, 7, 31) + offset_sunday == datetime(2013, 8, 25) | ||||
|  | ||||
|     on_offset_cases = [ | ||||
|         (WeekDay.SUN, datetime(2013, 1, 27), True), | ||||
|         (WeekDay.SAT, datetime(2013, 3, 30), True), | ||||
|         (WeekDay.MON, datetime(2013, 2, 18), False),  # Not the last Mon | ||||
|         (WeekDay.SUN, datetime(2013, 2, 25), False),  # Not a SUN | ||||
|         (WeekDay.MON, datetime(2013, 2, 25), True), | ||||
|         (WeekDay.SAT, datetime(2013, 11, 30), True), | ||||
|         (WeekDay.SAT, datetime(2006, 8, 26), True), | ||||
|         (WeekDay.SAT, datetime(2007, 8, 25), True), | ||||
|         (WeekDay.SAT, datetime(2008, 8, 30), True), | ||||
|         (WeekDay.SAT, datetime(2009, 8, 29), True), | ||||
|         (WeekDay.SAT, datetime(2010, 8, 28), True), | ||||
|         (WeekDay.SAT, datetime(2011, 8, 27), True), | ||||
|         (WeekDay.SAT, datetime(2019, 8, 31), True), | ||||
|     ] | ||||
|  | ||||
|     @pytest.mark.parametrize("case", on_offset_cases) | ||||
|     def test_is_on_offset(self, case): | ||||
|         weekday, dt, expected = case | ||||
|         offset = LastWeekOfMonth(weekday=weekday) | ||||
|         assert offset.is_on_offset(dt) == expected | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "n,weekday,date,tz", | ||||
|         [ | ||||
|             (4, 6, "1917-05-27 20:55:27.084284178+0200", "Europe/Warsaw"), | ||||
|             (-4, 5, "2005-08-27 05:01:42.799392561-0500", "America/Rainy_River"), | ||||
|         ], | ||||
|     ) | ||||
|     def test_last_week_of_month_on_offset(self, n, weekday, date, tz): | ||||
|         # GH 19036, GH 18977 _adjust_dst was incorrect for LastWeekOfMonth | ||||
|         offset = LastWeekOfMonth(n=n, weekday=weekday) | ||||
|         ts = Timestamp(date, tz=tz) | ||||
|         slow = (ts + offset) - offset == ts | ||||
|         fast = offset.is_on_offset(ts) | ||||
|         assert fast == slow | ||||
|  | ||||
|     def test_repr(self): | ||||
|         assert ( | ||||
|             repr(LastWeekOfMonth(n=2, weekday=1)) == "<2 * LastWeekOfMonths: weekday=1>" | ||||
|         ) | ||||
| @ -0,0 +1,339 @@ | ||||
| """ | ||||
| Tests for the following offsets: | ||||
| - YearBegin | ||||
| - YearEnd | ||||
| """ | ||||
| from __future__ import annotations | ||||
|  | ||||
| from datetime import datetime | ||||
|  | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas import Timestamp | ||||
| from pandas.tests.tseries.offsets.common import ( | ||||
|     assert_is_on_offset, | ||||
|     assert_offset_equal, | ||||
| ) | ||||
|  | ||||
| from pandas.tseries.offsets import ( | ||||
|     YearBegin, | ||||
|     YearEnd, | ||||
| ) | ||||
|  | ||||
|  | ||||
| class TestYearBegin: | ||||
|     def test_misspecified(self): | ||||
|         with pytest.raises(ValueError, match="Month must go from 1 to 12"): | ||||
|             YearBegin(month=13) | ||||
|  | ||||
|     offset_cases = [] | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             YearBegin(), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2009, 1, 1), | ||||
|                 datetime(2008, 6, 30): datetime(2009, 1, 1), | ||||
|                 datetime(2008, 12, 31): datetime(2009, 1, 1), | ||||
|                 datetime(2005, 12, 30): datetime(2006, 1, 1), | ||||
|                 datetime(2005, 12, 31): datetime(2006, 1, 1), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             YearBegin(0), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 1, 1), | ||||
|                 datetime(2008, 6, 30): datetime(2009, 1, 1), | ||||
|                 datetime(2008, 12, 31): datetime(2009, 1, 1), | ||||
|                 datetime(2005, 12, 30): datetime(2006, 1, 1), | ||||
|                 datetime(2005, 12, 31): datetime(2006, 1, 1), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             YearBegin(3), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2011, 1, 1), | ||||
|                 datetime(2008, 6, 30): datetime(2011, 1, 1), | ||||
|                 datetime(2008, 12, 31): datetime(2011, 1, 1), | ||||
|                 datetime(2005, 12, 30): datetime(2008, 1, 1), | ||||
|                 datetime(2005, 12, 31): datetime(2008, 1, 1), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             YearBegin(-1), | ||||
|             { | ||||
|                 datetime(2007, 1, 1): datetime(2006, 1, 1), | ||||
|                 datetime(2007, 1, 15): datetime(2007, 1, 1), | ||||
|                 datetime(2008, 6, 30): datetime(2008, 1, 1), | ||||
|                 datetime(2008, 12, 31): datetime(2008, 1, 1), | ||||
|                 datetime(2006, 12, 29): datetime(2006, 1, 1), | ||||
|                 datetime(2006, 12, 30): datetime(2006, 1, 1), | ||||
|                 datetime(2007, 1, 1): datetime(2006, 1, 1), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             YearBegin(-2), | ||||
|             { | ||||
|                 datetime(2007, 1, 1): datetime(2005, 1, 1), | ||||
|                 datetime(2008, 6, 30): datetime(2007, 1, 1), | ||||
|                 datetime(2008, 12, 31): datetime(2007, 1, 1), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             YearBegin(month=4), | ||||
|             { | ||||
|                 datetime(2007, 4, 1): datetime(2008, 4, 1), | ||||
|                 datetime(2007, 4, 15): datetime(2008, 4, 1), | ||||
|                 datetime(2007, 3, 1): datetime(2007, 4, 1), | ||||
|                 datetime(2007, 12, 15): datetime(2008, 4, 1), | ||||
|                 datetime(2012, 1, 31): datetime(2012, 4, 1), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             YearBegin(0, month=4), | ||||
|             { | ||||
|                 datetime(2007, 4, 1): datetime(2007, 4, 1), | ||||
|                 datetime(2007, 3, 1): datetime(2007, 4, 1), | ||||
|                 datetime(2007, 12, 15): datetime(2008, 4, 1), | ||||
|                 datetime(2012, 1, 31): datetime(2012, 4, 1), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             YearBegin(4, month=4), | ||||
|             { | ||||
|                 datetime(2007, 4, 1): datetime(2011, 4, 1), | ||||
|                 datetime(2007, 4, 15): datetime(2011, 4, 1), | ||||
|                 datetime(2007, 3, 1): datetime(2010, 4, 1), | ||||
|                 datetime(2007, 12, 15): datetime(2011, 4, 1), | ||||
|                 datetime(2012, 1, 31): datetime(2015, 4, 1), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             YearBegin(-1, month=4), | ||||
|             { | ||||
|                 datetime(2007, 4, 1): datetime(2006, 4, 1), | ||||
|                 datetime(2007, 3, 1): datetime(2006, 4, 1), | ||||
|                 datetime(2007, 12, 15): datetime(2007, 4, 1), | ||||
|                 datetime(2012, 1, 31): datetime(2011, 4, 1), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             YearBegin(-3, month=4), | ||||
|             { | ||||
|                 datetime(2007, 4, 1): datetime(2004, 4, 1), | ||||
|                 datetime(2007, 3, 1): datetime(2004, 4, 1), | ||||
|                 datetime(2007, 12, 15): datetime(2005, 4, 1), | ||||
|                 datetime(2012, 1, 31): datetime(2009, 4, 1), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     @pytest.mark.parametrize("case", offset_cases) | ||||
|     def test_offset(self, case): | ||||
|         offset, cases = case | ||||
|         for base, expected in cases.items(): | ||||
|             assert_offset_equal(offset, base, expected) | ||||
|  | ||||
|     on_offset_cases = [ | ||||
|         (YearBegin(), datetime(2007, 1, 3), False), | ||||
|         (YearBegin(), datetime(2008, 1, 1), True), | ||||
|         (YearBegin(), datetime(2006, 12, 31), False), | ||||
|         (YearBegin(), datetime(2006, 1, 2), False), | ||||
|     ] | ||||
|  | ||||
|     @pytest.mark.parametrize("case", on_offset_cases) | ||||
|     def test_is_on_offset(self, case): | ||||
|         offset, dt, expected = case | ||||
|         assert_is_on_offset(offset, dt, expected) | ||||
|  | ||||
|  | ||||
| class TestYearEnd: | ||||
|     def test_misspecified(self): | ||||
|         with pytest.raises(ValueError, match="Month must go from 1 to 12"): | ||||
|             YearEnd(month=13) | ||||
|  | ||||
|     offset_cases = [] | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             YearEnd(), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 12, 31), | ||||
|                 datetime(2008, 6, 30): datetime(2008, 12, 31), | ||||
|                 datetime(2008, 12, 31): datetime(2009, 12, 31), | ||||
|                 datetime(2005, 12, 30): datetime(2005, 12, 31), | ||||
|                 datetime(2005, 12, 31): datetime(2006, 12, 31), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             YearEnd(0), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 12, 31), | ||||
|                 datetime(2008, 6, 30): datetime(2008, 12, 31), | ||||
|                 datetime(2008, 12, 31): datetime(2008, 12, 31), | ||||
|                 datetime(2005, 12, 30): datetime(2005, 12, 31), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             YearEnd(-1), | ||||
|             { | ||||
|                 datetime(2007, 1, 1): datetime(2006, 12, 31), | ||||
|                 datetime(2008, 6, 30): datetime(2007, 12, 31), | ||||
|                 datetime(2008, 12, 31): datetime(2007, 12, 31), | ||||
|                 datetime(2006, 12, 29): datetime(2005, 12, 31), | ||||
|                 datetime(2006, 12, 30): datetime(2005, 12, 31), | ||||
|                 datetime(2007, 1, 1): datetime(2006, 12, 31), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             YearEnd(-2), | ||||
|             { | ||||
|                 datetime(2007, 1, 1): datetime(2005, 12, 31), | ||||
|                 datetime(2008, 6, 30): datetime(2006, 12, 31), | ||||
|                 datetime(2008, 12, 31): datetime(2006, 12, 31), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     @pytest.mark.parametrize("case", offset_cases) | ||||
|     def test_offset(self, case): | ||||
|         offset, cases = case | ||||
|         for base, expected in cases.items(): | ||||
|             assert_offset_equal(offset, base, expected) | ||||
|  | ||||
|     on_offset_cases = [ | ||||
|         (YearEnd(), datetime(2007, 12, 31), True), | ||||
|         (YearEnd(), datetime(2008, 1, 1), False), | ||||
|         (YearEnd(), datetime(2006, 12, 31), True), | ||||
|         (YearEnd(), datetime(2006, 12, 29), False), | ||||
|     ] | ||||
|  | ||||
|     @pytest.mark.parametrize("case", on_offset_cases) | ||||
|     def test_is_on_offset(self, case): | ||||
|         offset, dt, expected = case | ||||
|         assert_is_on_offset(offset, dt, expected) | ||||
|  | ||||
|  | ||||
| class TestYearEndDiffMonth: | ||||
|     offset_cases = [] | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             YearEnd(month=3), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 3, 31), | ||||
|                 datetime(2008, 2, 15): datetime(2008, 3, 31), | ||||
|                 datetime(2008, 3, 31): datetime(2009, 3, 31), | ||||
|                 datetime(2008, 3, 30): datetime(2008, 3, 31), | ||||
|                 datetime(2005, 3, 31): datetime(2006, 3, 31), | ||||
|                 datetime(2006, 7, 30): datetime(2007, 3, 31), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             YearEnd(0, month=3), | ||||
|             { | ||||
|                 datetime(2008, 1, 1): datetime(2008, 3, 31), | ||||
|                 datetime(2008, 2, 28): datetime(2008, 3, 31), | ||||
|                 datetime(2008, 3, 31): datetime(2008, 3, 31), | ||||
|                 datetime(2005, 3, 30): datetime(2005, 3, 31), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             YearEnd(-1, month=3), | ||||
|             { | ||||
|                 datetime(2007, 1, 1): datetime(2006, 3, 31), | ||||
|                 datetime(2008, 2, 28): datetime(2007, 3, 31), | ||||
|                 datetime(2008, 3, 31): datetime(2007, 3, 31), | ||||
|                 datetime(2006, 3, 29): datetime(2005, 3, 31), | ||||
|                 datetime(2006, 3, 30): datetime(2005, 3, 31), | ||||
|                 datetime(2007, 3, 1): datetime(2006, 3, 31), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     offset_cases.append( | ||||
|         ( | ||||
|             YearEnd(-2, month=3), | ||||
|             { | ||||
|                 datetime(2007, 1, 1): datetime(2005, 3, 31), | ||||
|                 datetime(2008, 6, 30): datetime(2007, 3, 31), | ||||
|                 datetime(2008, 3, 31): datetime(2006, 3, 31), | ||||
|             }, | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|     @pytest.mark.parametrize("case", offset_cases) | ||||
|     def test_offset(self, case): | ||||
|         offset, cases = case | ||||
|         for base, expected in cases.items(): | ||||
|             assert_offset_equal(offset, base, expected) | ||||
|  | ||||
|     on_offset_cases = [ | ||||
|         (YearEnd(month=3), datetime(2007, 3, 31), True), | ||||
|         (YearEnd(month=3), datetime(2008, 1, 1), False), | ||||
|         (YearEnd(month=3), datetime(2006, 3, 31), True), | ||||
|         (YearEnd(month=3), datetime(2006, 3, 29), False), | ||||
|     ] | ||||
|  | ||||
|     @pytest.mark.parametrize("case", on_offset_cases) | ||||
|     def test_is_on_offset(self, case): | ||||
|         offset, dt, expected = case | ||||
|         assert_is_on_offset(offset, dt, expected) | ||||
|  | ||||
|  | ||||
| def test_add_out_of_pydatetime_range(): | ||||
|     # GH#50348 don't raise in Timestamp.replace | ||||
|     ts = Timestamp(np.datetime64("-20000-12-31")) | ||||
|     off = YearEnd() | ||||
|  | ||||
|     result = ts + off | ||||
|     # TODO(cython3): "arg: datetime" annotation will impose | ||||
|     # datetime limitations on Timestamp. The fused type below works in cy3 | ||||
|     # ctypedef fused datetimelike: | ||||
|     #     _Timestamp | ||||
|     #     datetime | ||||
|     # expected = Timestamp(np.datetime64("-19999-12-31")) | ||||
|     # assert result == expected | ||||
|     assert result.year in (-19999, 1973) | ||||
|     assert result.month == 12 | ||||
|     assert result.day == 31 | ||||
		Reference in New Issue
	
	Block a user