virtuelle Umgebung teil20b
This commit is contained in:
		
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -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,42 @@
 | 
			
		||||
import datetime
 | 
			
		||||
 | 
			
		||||
import pytest
 | 
			
		||||
 | 
			
		||||
from pandas._libs.tslibs import Timestamp
 | 
			
		||||
from pandas._libs.tslibs.offsets import MonthOffset
 | 
			
		||||
 | 
			
		||||
from pandas.tseries import offsets
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture(
 | 
			
		||||
    params=[
 | 
			
		||||
        getattr(offsets, o) for o in offsets.__all__ if o not in ("Tick", "BaseOffset")
 | 
			
		||||
    ]
 | 
			
		||||
)
 | 
			
		||||
def offset_types(request):
 | 
			
		||||
    """
 | 
			
		||||
    Fixture for all the datetime offsets available for a time series.
 | 
			
		||||
    """
 | 
			
		||||
    return request.param
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture(
 | 
			
		||||
    params=[
 | 
			
		||||
        getattr(offsets, o)
 | 
			
		||||
        for o in offsets.__all__
 | 
			
		||||
        if issubclass(getattr(offsets, o), MonthOffset) and o != "MonthOffset"
 | 
			
		||||
    ]
 | 
			
		||||
)
 | 
			
		||||
def month_classes(request):
 | 
			
		||||
    """
 | 
			
		||||
    Fixture for month based datetime offsets available for a time series.
 | 
			
		||||
    """
 | 
			
		||||
    return request.param
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def dt():
 | 
			
		||||
    """
 | 
			
		||||
    Fixture for common Timestamp.
 | 
			
		||||
    """
 | 
			
		||||
    return Timestamp(datetime.datetime(2008, 1, 2))
 | 
			
		||||
@@ -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="T")
 | 
			
		||||
    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,308 @@
 | 
			
		||||
"""
 | 
			
		||||
Tests for the following offsets:
 | 
			
		||||
- BQuarterBegin
 | 
			
		||||
- BQuarterEnd
 | 
			
		||||
"""
 | 
			
		||||
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 (
 | 
			
		||||
    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):
 | 
			
		||||
        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):
 | 
			
		||||
        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,267 @@
 | 
			
		||||
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.node.add_marker(
 | 
			
		||||
                pytest.mark.xfail(reason="OverflowError inside tzlocal past 2038")
 | 
			
		||||
            )
 | 
			
		||||
        elif (
 | 
			
		||||
            isinstance(tz, tzlocal)
 | 
			
		||||
            and is_platform_windows()
 | 
			
		||||
            and _offset in (QuarterEnd, BQuarterBegin, BQuarterEnd)
 | 
			
		||||
        ):
 | 
			
		||||
            request.node.add_marker(
 | 
			
		||||
                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):
 | 
			
		||||
    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,458 @@
 | 
			
		||||
"""
 | 
			
		||||
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,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
from pandas import (
 | 
			
		||||
    _testing as tm,
 | 
			
		||||
    date_range,
 | 
			
		||||
)
 | 
			
		||||
from pandas.tests.tseries.offsets.common import (
 | 
			
		||||
    assert_is_on_offset,
 | 
			
		||||
    assert_offset_equal,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
from pandas.tseries import offsets
 | 
			
		||||
from pandas.tseries.holiday import USFederalHolidayCalendar
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@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.filterwarnings("ignore:Non:pandas.errors.PerformanceWarning")
 | 
			
		||||
    def test_datetimeindex(self):
 | 
			
		||||
        hcal = USFederalHolidayCalendar()
 | 
			
		||||
        cbmb = CBMonthBegin(calendar=hcal)
 | 
			
		||||
        assert date_range(start="20120101", end="20130101", freq=cbmb).tolist()[
 | 
			
		||||
            0
 | 
			
		||||
        ] == datetime(2012, 1, 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.filterwarnings("ignore:Non:pandas.errors.PerformanceWarning")
 | 
			
		||||
    def test_datetimeindex(self):
 | 
			
		||||
        hcal = USFederalHolidayCalendar()
 | 
			
		||||
        freq = CBMonthEnd(calendar=hcal)
 | 
			
		||||
 | 
			
		||||
        assert date_range(start="20120101", end="20130101", freq=freq).tolist()[
 | 
			
		||||
            0
 | 
			
		||||
        ] == datetime(2012, 1, 31)
 | 
			
		||||
 | 
			
		||||
    @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,234 @@
 | 
			
		||||
"""
 | 
			
		||||
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.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})
 | 
			
		||||
 | 
			
		||||
        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,652 @@
 | 
			
		||||
"""
 | 
			
		||||
Tests for Fiscal Year and Fiscal Quarter offset classes
 | 
			
		||||
"""
 | 
			
		||||
from datetime import datetime
 | 
			
		||||
 | 
			
		||||
from dateutil.relativedelta import relativedelta
 | 
			
		||||
import pytest
 | 
			
		||||
 | 
			
		||||
from pandas import Timestamp
 | 
			
		||||
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):
 | 
			
		||||
        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="T")
 | 
			
		||||
    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,677 @@
 | 
			
		||||
"""
 | 
			
		||||
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,
 | 
			
		||||
    date_range,
 | 
			
		||||
)
 | 
			
		||||
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)
 | 
			
		||||
 | 
			
		||||
        # ensure generating a range with DatetimeIndex gives same result
 | 
			
		||||
        result = date_range(start=dates[0], end=dates[-1], freq="SM")
 | 
			
		||||
        exp = DatetimeIndex(dates, freq="SM")
 | 
			
		||||
        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)
 | 
			
		||||
 | 
			
		||||
        # ensure generating a range with DatetimeIndex gives same result
 | 
			
		||||
        result = date_range(start=dates[0], end=dates[-1], freq="SMS")
 | 
			
		||||
        exp = DatetimeIndex(dates, freq="SMS")
 | 
			
		||||
        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,296 @@
 | 
			
		||||
"""
 | 
			
		||||
Tests for the following offsets:
 | 
			
		||||
- QuarterBegin
 | 
			
		||||
- QuarterEnd
 | 
			
		||||
"""
 | 
			
		||||
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 (
 | 
			
		||||
    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):
 | 
			
		||||
        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):
 | 
			
		||||
        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,391 @@
 | 
			
		||||
"""
 | 
			
		||||
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 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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@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.delta == 1
 | 
			
		||||
    assert off / off.delta.to_timedelta64() == 1
 | 
			
		||||
 | 
			
		||||
    assert off / Nano(1) == off.delta / Nano(1).delta
 | 
			
		||||
 | 
			
		||||
    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.delta == off.delta / 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.delta == off.delta / 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.delta
 | 
			
		||||
    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):
 | 
			
		||||
    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.delta
 | 
			
		||||
 | 
			
		||||
    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,347 @@
 | 
			
		||||
"""
 | 
			
		||||
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,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
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):
 | 
			
		||||
        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