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)
Exemplo n.º 2
0
class TestBusinessHour(Base):
    _offset = BusinessHour

    def setup_method(self, method):
        self.d = datetime(2014, 7, 1, 10, 00)

        self.offset1 = BusinessHour()
        self.offset2 = BusinessHour(n=3)

        self.offset3 = BusinessHour(n=-1)
        self.offset4 = BusinessHour(n=-4)

        from datetime import time as dt_time

        self.offset5 = BusinessHour(start=dt_time(11, 0), end=dt_time(14, 30))
        self.offset6 = BusinessHour(start="20:00", end="05:00")
        self.offset7 = BusinessHour(n=-2,
                                    start=dt_time(21, 30),
                                    end=dt_time(6, 30))
        self.offset8 = BusinessHour(start=["09:00", "13:00"],
                                    end=["12:00", "17:00"])
        self.offset9 = BusinessHour(n=3,
                                    start=["09:00", "22:00"],
                                    end=["13:00", "03:00"])
        self.offset10 = BusinessHour(n=-1,
                                     start=["23:00", "13:00"],
                                     end=["02:00", "17:00"])

    @pytest.mark.parametrize(
        "start,end,match",
        [
            (
                dt_time(11, 0, 5),
                "17:00",
                "time data must be specified only with hour and minute",
            ),
            ("AAA", "17:00", "time data must match '%H:%M' format"),
            ("14:00:05", "17:00", "time data must match '%H:%M' format"),
            ([], "17:00", "Must include at least 1 start time"),
            ("09:00", [], "Must include at least 1 end time"),
            (
                ["09:00", "11:00"],
                "17:00",
                "number of starting time and ending time must be the same",
            ),
            (
                ["09:00", "11:00"],
                ["10:00"],
                "number of starting time and ending time must be the same",
            ),
            (
                ["09:00", "11:00"],
                ["12:00", "20:00"],
                r"invalid starting and ending time\(s\): opening hours should not "
                "touch or overlap with one another",
            ),
            (
                ["12:00", "20:00"],
                ["09:00", "11:00"],
                r"invalid starting and ending time\(s\): opening hours should not "
                "touch or overlap with one another",
            ),
        ],
    )
    def test_constructor_errors(self, start, end, match):
        with pytest.raises(ValueError, match=match):
            BusinessHour(start=start, end=end)

    def test_different_normalize_equals(self):
        # GH#21404 changed __eq__ to return False when `normalize` does not match
        offset = self._offset()
        offset2 = self._offset(normalize=True)
        assert offset != offset2

    def test_repr(self):
        assert repr(self.offset1) == "<BusinessHour: BH=09:00-17:00>"
        assert repr(self.offset2) == "<3 * BusinessHours: BH=09:00-17:00>"
        assert repr(self.offset3) == "<-1 * BusinessHour: BH=09:00-17:00>"
        assert repr(self.offset4) == "<-4 * BusinessHours: BH=09:00-17:00>"

        assert repr(self.offset5) == "<BusinessHour: BH=11:00-14:30>"
        assert repr(self.offset6) == "<BusinessHour: BH=20:00-05:00>"
        assert repr(self.offset7) == "<-2 * BusinessHours: BH=21:30-06:30>"
        assert repr(
            self.offset8) == "<BusinessHour: BH=09:00-12:00,13:00-17:00>"
        assert repr(
            self.offset9) == "<3 * BusinessHours: BH=09:00-13:00,22:00-03:00>"
        assert repr(
            self.offset10) == "<-1 * BusinessHour: BH=13:00-17:00,23:00-02:00>"

    def test_with_offset(self):
        expected = Timestamp("2014-07-01 13:00")

        assert self.d + BusinessHour() * 3 == expected
        assert self.d + BusinessHour(n=3) == expected

    @pytest.mark.parametrize(
        "offset_name",
        [
            "offset1", "offset2", "offset3", "offset4", "offset8", "offset9",
            "offset10"
        ],
    )
    def test_eq_attribute(self, offset_name):
        offset = getattr(self, offset_name)
        assert offset == offset

    @pytest.mark.parametrize(
        "offset1,offset2",
        [
            (BusinessHour(start="09:00"), BusinessHour()),
            (
                BusinessHour(start=["23:00", "13:00"], end=["12:00", "17:00"]),
                BusinessHour(start=["13:00", "23:00"], end=["17:00", "12:00"]),
            ),
        ],
    )
    def test_eq(self, offset1, offset2):
        assert offset1 == offset2

    @pytest.mark.parametrize(
        "offset1,offset2",
        [
            (BusinessHour(), BusinessHour(-1)),
            (BusinessHour(start="09:00"), BusinessHour(start="09:01")),
            (
                BusinessHour(start="09:00", end="17:00"),
                BusinessHour(start="17:00", end="09:01"),
            ),
            (
                BusinessHour(start=["13:00", "23:00"], end=["18:00", "07:00"]),
                BusinessHour(start=["13:00", "23:00"], end=["17:00", "12:00"]),
            ),
        ],
    )
    def test_neq(self, offset1, offset2):
        assert offset1 != offset2

    @pytest.mark.parametrize(
        "offset_name",
        [
            "offset1", "offset2", "offset3", "offset4", "offset8", "offset9",
            "offset10"
        ],
    )
    def test_hash(self, offset_name):
        offset = getattr(self, offset_name)
        assert offset == offset

    def test_call(self):
        with tm.assert_produces_warning(FutureWarning):
            # GH#34171 DateOffset.__call__ is deprecated
            assert self.offset1(self.d) == datetime(2014, 7, 1, 11)
            assert self.offset2(self.d) == datetime(2014, 7, 1, 13)
            assert self.offset3(self.d) == datetime(2014, 6, 30, 17)
            assert self.offset4(self.d) == datetime(2014, 6, 30, 14)
            assert self.offset8(self.d) == datetime(2014, 7, 1, 11)
            assert self.offset9(self.d) == datetime(2014, 7, 1, 22)
            assert self.offset10(self.d) == datetime(2014, 7, 1, 1)

    def test_sub(self):
        # we have to override test_sub here because self.offset2 is not
        # defined as self._offset(2)
        off = self.offset2
        msg = "Cannot subtract datetime from offset"
        with pytest.raises(TypeError, match=msg):
            off - self.d
        assert 2 * off - off == off

        assert self.d - self.offset2 == self.d + self._offset(-3)

    def testRollback1(self):
        assert self.offset1.rollback(self.d) == self.d
        assert self.offset2.rollback(self.d) == self.d
        assert self.offset3.rollback(self.d) == self.d
        assert self.offset4.rollback(self.d) == self.d
        assert self.offset5.rollback(self.d) == datetime(2014, 6, 30, 14, 30)
        assert self.offset6.rollback(self.d) == datetime(2014, 7, 1, 5, 0)
        assert self.offset7.rollback(self.d) == datetime(2014, 7, 1, 6, 30)
        assert self.offset8.rollback(self.d) == self.d
        assert self.offset9.rollback(self.d) == self.d
        assert self.offset10.rollback(self.d) == datetime(2014, 7, 1, 2)

        d = datetime(2014, 7, 1, 0)
        assert self.offset1.rollback(d) == datetime(2014, 6, 30, 17)
        assert self.offset2.rollback(d) == datetime(2014, 6, 30, 17)
        assert self.offset3.rollback(d) == datetime(2014, 6, 30, 17)
        assert self.offset4.rollback(d) == datetime(2014, 6, 30, 17)
        assert self.offset5.rollback(d) == datetime(2014, 6, 30, 14, 30)
        assert self.offset6.rollback(d) == d
        assert self.offset7.rollback(d) == d
        assert self.offset8.rollback(d) == datetime(2014, 6, 30, 17)
        assert self.offset9.rollback(d) == d
        assert self.offset10.rollback(d) == d

        assert self._offset(5).rollback(self.d) == self.d

    def testRollback2(self):
        assert self._offset(-3).rollback(datetime(2014, 7, 5, 15,
                                                  0)) == datetime(
                                                      2014, 7, 4, 17, 0)

    def testRollforward1(self):
        assert self.offset1.rollforward(self.d) == self.d
        assert self.offset2.rollforward(self.d) == self.d
        assert self.offset3.rollforward(self.d) == self.d
        assert self.offset4.rollforward(self.d) == self.d
        assert self.offset5.rollforward(self.d) == datetime(2014, 7, 1, 11, 0)
        assert self.offset6.rollforward(self.d) == datetime(2014, 7, 1, 20, 0)
        assert self.offset7.rollforward(self.d) == datetime(2014, 7, 1, 21, 30)
        assert self.offset8.rollforward(self.d) == self.d
        assert self.offset9.rollforward(self.d) == self.d
        assert self.offset10.rollforward(self.d) == datetime(2014, 7, 1, 13)

        d = datetime(2014, 7, 1, 0)
        assert self.offset1.rollforward(d) == datetime(2014, 7, 1, 9)
        assert self.offset2.rollforward(d) == datetime(2014, 7, 1, 9)
        assert self.offset3.rollforward(d) == datetime(2014, 7, 1, 9)
        assert self.offset4.rollforward(d) == datetime(2014, 7, 1, 9)
        assert self.offset5.rollforward(d) == datetime(2014, 7, 1, 11)
        assert self.offset6.rollforward(d) == d
        assert self.offset7.rollforward(d) == d
        assert self.offset8.rollforward(d) == datetime(2014, 7, 1, 9)
        assert self.offset9.rollforward(d) == d
        assert self.offset10.rollforward(d) == d

        assert self._offset(5).rollforward(self.d) == self.d

    def testRollforward2(self):
        assert self._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 = []
    normalize_cases.append((
        BusinessHour(normalize=True),
        {
            datetime(2014, 7, 1, 8): datetime(2014, 7, 1),
            datetime(2014, 7, 1, 17): datetime(2014, 7, 2),
            datetime(2014, 7, 1, 16): datetime(2014, 7, 2),
            datetime(2014, 7, 1, 23): datetime(2014, 7, 2),
            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),
        },
    ))

    normalize_cases.append((
        BusinessHour(-1, normalize=True),
        {
            datetime(2014, 7, 1, 8): datetime(2014, 6, 30),
            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, 30),
            datetime(2014, 7, 1, 0): datetime(2014, 6, 30),
            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),
        },
    ))

    normalize_cases.append((
        BusinessHour(1, normalize=True, start="17:00", end="04:00"),
        {
            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, 2),
            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("case", normalize_cases)
    def test_normalize(self, case):
        offset, cases = case
        for dt, expected in cases.items():
            assert offset.apply(dt) == expected

    on_offset_cases = []
    on_offset_cases.append((
        BusinessHour(),
        {
            datetime(2014, 7, 1, 9): True,
            datetime(2014, 7, 1, 8, 59): False,
            datetime(2014, 7, 1, 8): False,
            datetime(2014, 7, 1, 17): True,
            datetime(2014, 7, 1, 17, 1): False,
            datetime(2014, 7, 1, 18): False,
            datetime(2014, 7, 5, 9): False,
            datetime(2014, 7, 6, 12): False,
        },
    ))

    on_offset_cases.append((
        BusinessHour(start="10:00", end="15:00"),
        {
            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,
        },
    ))

    on_offset_cases.append((
        BusinessHour(start="19:00", end="05:00"),
        {
            datetime(2014, 7, 1, 9, 0): False,
            datetime(2014, 7, 1, 10, 0): False,
            datetime(2014, 7, 1, 15): False,
            datetime(2014, 7, 1, 15, 1): False,
            datetime(2014, 7, 5, 12, 0): False,
            datetime(2014, 7, 6, 12, 0): False,
            datetime(2014, 7, 1, 19, 0): True,
            datetime(2014, 7, 2, 0, 0): True,
            datetime(2014, 7, 4, 23): True,
            datetime(2014, 7, 5, 1): True,
            datetime(2014, 7, 5, 5, 0): True,
            datetime(2014, 7, 6, 23, 0): False,
            datetime(2014, 7, 7, 3, 0): False,
        },
    ))

    on_offset_cases.append((
        BusinessHour(start=["09:00", "13:00"], end=["12:00", "17:00"]),
        {
            datetime(2014, 7, 1, 9): True,
            datetime(2014, 7, 1, 8, 59): False,
            datetime(2014, 7, 1, 8): False,
            datetime(2014, 7, 1, 17): True,
            datetime(2014, 7, 1, 17, 1): False,
            datetime(2014, 7, 1, 18): False,
            datetime(2014, 7, 5, 9): False,
            datetime(2014, 7, 6, 12): False,
            datetime(2014, 7, 1, 12, 30): False,
        },
    ))

    on_offset_cases.append((
        BusinessHour(start=["19:00", "23:00"], end=["21:00", "05:00"]),
        {
            datetime(2014, 7, 1, 9, 0): False,
            datetime(2014, 7, 1, 10, 0): False,
            datetime(2014, 7, 1, 15): False,
            datetime(2014, 7, 1, 15, 1): False,
            datetime(2014, 7, 5, 12, 0): False,
            datetime(2014, 7, 6, 12, 0): False,
            datetime(2014, 7, 1, 19, 0): True,
            datetime(2014, 7, 2, 0, 0): True,
            datetime(2014, 7, 4, 23): True,
            datetime(2014, 7, 5, 1): True,
            datetime(2014, 7, 5, 5, 0): True,
            datetime(2014, 7, 6, 23, 0): False,
            datetime(2014, 7, 7, 3, 0): False,
            datetime(2014, 7, 4, 22): False,
        },
    ))

    @pytest.mark.parametrize("case", on_offset_cases)
    def test_is_on_offset(self, case):
        offset, cases = case
        for dt, expected in cases.items():
            assert offset.is_on_offset(dt) == expected

    apply_cases = [
        (
            BusinessHour(),
            {
                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, 2, 10),
                datetime(2014, 7, 1, 16):
                datetime(2014, 7, 2, 9),
                datetime(2014, 7, 1, 16, 30, 15):
                datetime(2014, 7, 2, 9, 30, 15),
                datetime(2014, 7, 1, 17):
                datetime(2014, 7, 2, 10),
                datetime(2014, 7, 2, 11):
                datetime(2014, 7, 2, 12),
                # out of business hours
                datetime(2014, 7, 2, 8):
                datetime(2014, 7, 2, 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),
            },
        ),
        (
            BusinessHour(4),
            {
                datetime(2014, 7, 1, 11): datetime(2014, 7, 1, 15),
                datetime(2014, 7, 1, 13): datetime(2014, 7, 2, 9),
                datetime(2014, 7, 1, 15): datetime(2014, 7, 2, 11),
                datetime(2014, 7, 1, 16): datetime(2014, 7, 2, 12),
                datetime(2014, 7, 1, 17): datetime(2014, 7, 2, 13),
                datetime(2014, 7, 2, 11): datetime(2014, 7, 2, 15),
                datetime(2014, 7, 2, 8): datetime(2014, 7, 2, 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),
            },
        ),
        (
            BusinessHour(-1),
            {
                datetime(2014, 7, 1, 11):
                datetime(2014, 7, 1, 10),
                datetime(2014, 7, 1, 13):
                datetime(2014, 7, 1, 12),
                datetime(2014, 7, 1, 15):
                datetime(2014, 7, 1, 14),
                datetime(2014, 7, 1, 16):
                datetime(2014, 7, 1, 15),
                datetime(2014, 7, 1, 10):
                datetime(2014, 6, 30, 17),
                datetime(2014, 7, 1, 16, 30, 15):
                datetime(2014, 7, 1, 15, 30, 15),
                datetime(2014, 7, 1, 9, 30, 15):
                datetime(2014, 6, 30, 16, 30, 15),
                datetime(2014, 7, 1, 17):
                datetime(2014, 7, 1, 16),
                datetime(2014, 7, 1, 5):
                datetime(2014, 6, 30, 16),
                datetime(2014, 7, 2, 11):
                datetime(2014, 7, 2, 10),
                # out of business hours
                datetime(2014, 7, 2, 8):
                datetime(2014, 7, 1, 16),
                datetime(2014, 7, 2, 19):
                datetime(2014, 7, 2, 16),
                datetime(2014, 7, 2, 23):
                datetime(2014, 7, 2, 16),
                datetime(2014, 7, 3, 0):
                datetime(2014, 7, 2, 16),
                # saturday
                datetime(2014, 7, 5, 15):
                datetime(2014, 7, 4, 16),
                datetime(2014, 7, 7, 9):
                datetime(2014, 7, 4, 16),
                datetime(2014, 7, 7, 9, 30):
                datetime(2014, 7, 4, 16, 30),
                datetime(2014, 7, 7, 9, 30, 30):
                datetime(2014, 7, 4, 16, 30, 30),
            },
        ),
        (
            BusinessHour(-4),
            {
                datetime(2014, 7, 1, 11): datetime(2014, 6, 30, 15),
                datetime(2014, 7, 1, 13): datetime(2014, 6, 30, 17),
                datetime(2014, 7, 1, 15): datetime(2014, 7, 1, 11),
                datetime(2014, 7, 1, 16): datetime(2014, 7, 1, 12),
                datetime(2014, 7, 1, 17): datetime(2014, 7, 1, 13),
                datetime(2014, 7, 2, 11): datetime(2014, 7, 1, 15),
                datetime(2014, 7, 2, 8): datetime(2014, 7, 1, 13),
                datetime(2014, 7, 2, 19): datetime(2014, 7, 2, 13),
                datetime(2014, 7, 2, 23): datetime(2014, 7, 2, 13),
                datetime(2014, 7, 3, 0): datetime(2014, 7, 2, 13),
                datetime(2014, 7, 5, 15): datetime(2014, 7, 4, 13),
                datetime(2014, 7, 4, 18): datetime(2014, 7, 4, 13),
                datetime(2014, 7, 7, 9, 30): datetime(2014, 7, 4, 13, 30),
                datetime(2014, 7, 7, 9, 30, 30):
                datetime(2014, 7, 4, 13, 30, 30),
            },
        ),
        (
            BusinessHour(start="13:00", end="16:00"),
            {
                datetime(2014, 7, 1, 11): datetime(2014, 7, 1, 14),
                datetime(2014, 7, 1, 13): datetime(2014, 7, 1, 14),
                datetime(2014, 7, 1, 15): datetime(2014, 7, 2, 13),
                datetime(2014, 7, 1, 19): datetime(2014, 7, 2, 14),
                datetime(2014, 7, 1, 16): datetime(2014, 7, 2, 14),
                datetime(2014, 7, 1, 15, 30, 15):
                datetime(2014, 7, 2, 13, 30, 15),
                datetime(2014, 7, 5, 15): datetime(2014, 7, 7, 14),
                datetime(2014, 7, 4, 17): datetime(2014, 7, 7, 14),
            },
        ),
        (
            BusinessHour(n=2, start="13:00", end="16:00"),
            {
                datetime(2014, 7, 1, 17): datetime(2014, 7, 2, 15),
                datetime(2014, 7, 2, 14): datetime(2014, 7, 3, 13),
                datetime(2014, 7, 2, 8): datetime(2014, 7, 2, 15),
                datetime(2014, 7, 2, 19): datetime(2014, 7, 3, 15),
                datetime(2014, 7, 2, 14, 30): datetime(2014, 7, 3, 13, 30),
                datetime(2014, 7, 3, 0): datetime(2014, 7, 3, 15),
                datetime(2014, 7, 5, 15): datetime(2014, 7, 7, 15),
                datetime(2014, 7, 4, 17): datetime(2014, 7, 7, 15),
                datetime(2014, 7, 4, 14, 30): datetime(2014, 7, 7, 13, 30),
                datetime(2014, 7, 4, 14, 30, 30):
                datetime(2014, 7, 7, 13, 30, 30),
            },
        ),
        (
            BusinessHour(n=-1, start="13:00", end="16:00"),
            {
                datetime(2014, 7, 2, 11): datetime(2014, 7, 1, 15),
                datetime(2014, 7, 2, 13): datetime(2014, 7, 1, 15),
                datetime(2014, 7, 2, 14): datetime(2014, 7, 1, 16),
                datetime(2014, 7, 2, 15): datetime(2014, 7, 2, 14),
                datetime(2014, 7, 2, 19): datetime(2014, 7, 2, 15),
                datetime(2014, 7, 2, 16): datetime(2014, 7, 2, 15),
                datetime(2014, 7, 2, 13, 30, 15):
                datetime(2014, 7, 1, 15, 30, 15),
                datetime(2014, 7, 5, 15): datetime(2014, 7, 4, 15),
                datetime(2014, 7, 7, 11): datetime(2014, 7, 4, 15),
            },
        ),
        (
            BusinessHour(n=-3, start="10:00", end="16:00"),
            {
                datetime(2014, 7, 1, 17): datetime(2014, 7, 1, 13),
                datetime(2014, 7, 2, 14): datetime(2014, 7, 2, 11),
                datetime(2014, 7, 2, 8): datetime(2014, 7, 1, 13),
                datetime(2014, 7, 2, 13): datetime(2014, 7, 1, 16),
                datetime(2014, 7, 2, 19): datetime(2014, 7, 2, 13),
                datetime(2014, 7, 2, 11, 30): datetime(2014, 7, 1, 14, 30),
                datetime(2014, 7, 3, 0): datetime(2014, 7, 2, 13),
                datetime(2014, 7, 4, 10): datetime(2014, 7, 3, 13),
                datetime(2014, 7, 5, 15): datetime(2014, 7, 4, 13),
                datetime(2014, 7, 4, 16): datetime(2014, 7, 4, 13),
                datetime(2014, 7, 4, 12, 30): datetime(2014, 7, 3, 15, 30),
                datetime(2014, 7, 4, 12, 30, 30):
                datetime(2014, 7, 3, 15, 30, 30),
            },
        ),
        (
            BusinessHour(start="19:00", end="05:00"),
            {
                datetime(2014, 7, 1, 17): datetime(2014, 7, 1, 20),
                datetime(2014, 7, 2, 14): datetime(2014, 7, 2, 20),
                datetime(2014, 7, 2, 8): datetime(2014, 7, 2, 20),
                datetime(2014, 7, 2, 13): datetime(2014, 7, 2, 20),
                datetime(2014, 7, 2, 19): datetime(2014, 7, 2, 20),
                datetime(2014, 7, 2, 4, 30): datetime(2014, 7, 2, 19, 30),
                datetime(2014, 7, 3, 0): datetime(2014, 7, 3, 1),
                datetime(2014, 7, 4, 10): datetime(2014, 7, 4, 20),
                datetime(2014, 7, 4, 23): datetime(2014, 7, 5, 0),
                datetime(2014, 7, 5, 0): datetime(2014, 7, 5, 1),
                datetime(2014, 7, 5, 4): datetime(2014, 7, 7, 19),
                datetime(2014, 7, 5, 4, 30): datetime(2014, 7, 7, 19, 30),
                datetime(2014, 7, 5, 4, 30, 30):
                datetime(2014, 7, 7, 19, 30, 30),
            },
        ),
        (
            BusinessHour(n=-1, start="19:00", end="05:00"),
            {
                datetime(2014, 7, 1, 17): datetime(2014, 7, 1, 4),
                datetime(2014, 7, 2, 14): datetime(2014, 7, 2, 4),
                datetime(2014, 7, 2, 8): datetime(2014, 7, 2, 4),
                datetime(2014, 7, 2, 13): datetime(2014, 7, 2, 4),
                datetime(2014, 7, 2, 20): datetime(2014, 7, 2, 5),
                datetime(2014, 7, 2, 19): datetime(2014, 7, 2, 4),
                datetime(2014, 7, 2, 19, 30): datetime(2014, 7, 2, 4, 30),
                datetime(2014, 7, 3, 0): datetime(2014, 7, 2, 23),
                datetime(2014, 7, 3, 6): datetime(2014, 7, 3, 4),
                datetime(2014, 7, 4, 23): datetime(2014, 7, 4, 22),
                datetime(2014, 7, 5, 0): datetime(2014, 7, 4, 23),
                datetime(2014, 7, 5, 4): datetime(2014, 7, 5, 3),
                datetime(2014, 7, 7, 19, 30): datetime(2014, 7, 5, 4, 30),
                datetime(2014, 7, 7, 19, 30, 30):
                datetime(2014, 7, 5, 4, 30, 30),
            },
        ),
        (
            BusinessHour(n=4, start="00:00", end="23:00"),
            {
                datetime(2014, 7, 3, 22): datetime(2014, 7, 4, 3),
                datetime(2014, 7, 4, 22): datetime(2014, 7, 7, 3),
                datetime(2014, 7, 3, 22, 30): datetime(2014, 7, 4, 3, 30),
                datetime(2014, 7, 3, 22, 20): datetime(2014, 7, 4, 3, 20),
                datetime(2014, 7, 4, 22, 30, 30):
                datetime(2014, 7, 7, 3, 30, 30),
                datetime(2014, 7, 4, 22, 30, 20):
                datetime(2014, 7, 7, 3, 30, 20),
            },
        ),
        (
            BusinessHour(n=-4, start="00:00", end="23:00"),
            {
                datetime(2014, 7, 4, 3): datetime(2014, 7, 3, 22),
                datetime(2014, 7, 7, 3): datetime(2014, 7, 4, 22),
                datetime(2014, 7, 4, 3, 30): datetime(2014, 7, 3, 22, 30),
                datetime(2014, 7, 4, 3, 20): datetime(2014, 7, 3, 22, 20),
                datetime(2014, 7, 7, 3, 30, 30):
                datetime(2014, 7, 4, 22, 30, 30),
                datetime(2014, 7, 7, 3, 30, 20):
                datetime(2014, 7, 4, 22, 30, 20),
            },
        ),
        (
            BusinessHour(start=["09:00", "14:00"], end=["12:00", "18:00"]),
            {
                datetime(2014, 7, 1, 11):
                datetime(2014, 7, 1, 14),
                datetime(2014, 7, 1, 15):
                datetime(2014, 7, 1, 16),
                datetime(2014, 7, 1, 19):
                datetime(2014, 7, 2, 10),
                datetime(2014, 7, 1, 16):
                datetime(2014, 7, 1, 17),
                datetime(2014, 7, 1, 16, 30, 15):
                datetime(2014, 7, 1, 17, 30, 15),
                datetime(2014, 7, 1, 17):
                datetime(2014, 7, 2, 9),
                datetime(2014, 7, 2, 11):
                datetime(2014, 7, 2, 14),
                # out of business hours
                datetime(2014, 7, 1, 13):
                datetime(2014, 7, 1, 15),
                datetime(2014, 7, 2, 8):
                datetime(2014, 7, 2, 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, 9),
                datetime(2014, 7, 4, 17, 30):
                datetime(2014, 7, 7, 9, 30),
                datetime(2014, 7, 4, 17, 30, 30):
                datetime(2014, 7, 7, 9, 30, 30),
            },
        ),
        (
            BusinessHour(n=4, start=["09:00", "14:00"], end=["12:00",
                                                             "18:00"]),
            {
                datetime(2014, 7, 1, 11): datetime(2014, 7, 1, 17),
                datetime(2014, 7, 1, 13): datetime(2014, 7, 2, 9),
                datetime(2014, 7, 1, 15): datetime(2014, 7, 2, 10),
                datetime(2014, 7, 1, 16): datetime(2014, 7, 2, 11),
                datetime(2014, 7, 1, 17): datetime(2014, 7, 2, 14),
                datetime(2014, 7, 2, 11): datetime(2014, 7, 2, 17),
                datetime(2014, 7, 2, 8): datetime(2014, 7, 2, 15),
                datetime(2014, 7, 2, 19): datetime(2014, 7, 3, 15),
                datetime(2014, 7, 2, 23): datetime(2014, 7, 3, 15),
                datetime(2014, 7, 3, 0): datetime(2014, 7, 3, 15),
                datetime(2014, 7, 5, 15): datetime(2014, 7, 7, 15),
                datetime(2014, 7, 4, 17): datetime(2014, 7, 7, 14),
                datetime(2014, 7, 4, 16, 30): datetime(2014, 7, 7, 11, 30),
                datetime(2014, 7, 4, 16, 30, 30):
                datetime(2014, 7, 7, 11, 30, 30),
            },
        ),
        (
            BusinessHour(n=-4,
                         start=["09:00", "14:00"],
                         end=["12:00", "18:00"]),
            {
                datetime(2014, 7, 1, 11): datetime(2014, 6, 30, 16),
                datetime(2014, 7, 1, 13): datetime(2014, 6, 30, 17),
                datetime(2014, 7, 1, 15): datetime(2014, 6, 30, 18),
                datetime(2014, 7, 1, 16): datetime(2014, 7, 1, 10),
                datetime(2014, 7, 1, 17): datetime(2014, 7, 1, 11),
                datetime(2014, 7, 2, 11): datetime(2014, 7, 1, 16),
                datetime(2014, 7, 2, 8): datetime(2014, 7, 1, 12),
                datetime(2014, 7, 2, 19): datetime(2014, 7, 2, 12),
                datetime(2014, 7, 2, 23): datetime(2014, 7, 2, 12),
                datetime(2014, 7, 3, 0): datetime(2014, 7, 2, 12),
                datetime(2014, 7, 5, 15): datetime(2014, 7, 4, 12),
                datetime(2014, 7, 4, 18): datetime(2014, 7, 4, 12),
                datetime(2014, 7, 7, 9, 30): datetime(2014, 7, 4, 14, 30),
                datetime(2014, 7, 7, 9, 30, 30):
                datetime(2014, 7, 4, 14, 30, 30),
            },
        ),
        (
            BusinessHour(n=-1,
                         start=["19:00", "03:00"],
                         end=["01:00", "05:00"]),
            {
                datetime(2014, 7, 1, 17): datetime(2014, 7, 1, 4),
                datetime(2014, 7, 2, 14): datetime(2014, 7, 2, 4),
                datetime(2014, 7, 2, 8): datetime(2014, 7, 2, 4),
                datetime(2014, 7, 2, 13): datetime(2014, 7, 2, 4),
                datetime(2014, 7, 2, 20): datetime(2014, 7, 2, 5),
                datetime(2014, 7, 2, 19): datetime(2014, 7, 2, 4),
                datetime(2014, 7, 2, 4): datetime(2014, 7, 2, 1),
                datetime(2014, 7, 2, 19, 30): datetime(2014, 7, 2, 4, 30),
                datetime(2014, 7, 3, 0): datetime(2014, 7, 2, 23),
                datetime(2014, 7, 3, 6): datetime(2014, 7, 3, 4),
                datetime(2014, 7, 4, 23): datetime(2014, 7, 4, 22),
                datetime(2014, 7, 5, 0): datetime(2014, 7, 4, 23),
                datetime(2014, 7, 5, 4): datetime(2014, 7, 5, 0),
                datetime(2014, 7, 7, 3, 30): datetime(2014, 7, 5, 0, 30),
                datetime(2014, 7, 7, 19, 30): datetime(2014, 7, 7, 4, 30),
                datetime(2014, 7, 7, 19, 30, 30):
                datetime(2014, 7, 7, 4, 30, 30),
            },
        ),
    ]

    # long business hours (see gh-26381)

    # multiple business hours

    @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)

    apply_large_n_cases = [
        (
            # A week later
            BusinessHour(40),
            {
                datetime(2014, 7, 1, 11): datetime(2014, 7, 8, 11),
                datetime(2014, 7, 1, 13): datetime(2014, 7, 8, 13),
                datetime(2014, 7, 1, 15): datetime(2014, 7, 8, 15),
                datetime(2014, 7, 1, 16): datetime(2014, 7, 8, 16),
                datetime(2014, 7, 1, 17): datetime(2014, 7, 9, 9),
                datetime(2014, 7, 2, 11): datetime(2014, 7, 9, 11),
                datetime(2014, 7, 2, 8): datetime(2014, 7, 9, 9),
                datetime(2014, 7, 2, 19): datetime(2014, 7, 10, 9),
                datetime(2014, 7, 2, 23): datetime(2014, 7, 10, 9),
                datetime(2014, 7, 3, 0): datetime(2014, 7, 10, 9),
                datetime(2014, 7, 5, 15): datetime(2014, 7, 14, 9),
                datetime(2014, 7, 4, 18): datetime(2014, 7, 14, 9),
                datetime(2014, 7, 7, 9, 30): datetime(2014, 7, 14, 9, 30),
                datetime(2014, 7, 7, 9, 30, 30):
                datetime(2014, 7, 14, 9, 30, 30),
            },
        ),
        (
            # 3 days and 1 hour before
            BusinessHour(-25),
            {
                datetime(2014, 7, 1, 11): datetime(2014, 6, 26, 10),
                datetime(2014, 7, 1, 13): datetime(2014, 6, 26, 12),
                datetime(2014, 7, 1, 9): datetime(2014, 6, 25, 16),
                datetime(2014, 7, 1, 10): datetime(2014, 6, 25, 17),
                datetime(2014, 7, 3, 11): datetime(2014, 6, 30, 10),
                datetime(2014, 7, 3, 8): datetime(2014, 6, 27, 16),
                datetime(2014, 7, 3, 19): datetime(2014, 6, 30, 16),
                datetime(2014, 7, 3, 23): datetime(2014, 6, 30, 16),
                datetime(2014, 7, 4, 9): datetime(2014, 6, 30, 16),
                datetime(2014, 7, 5, 15): datetime(2014, 7, 1, 16),
                datetime(2014, 7, 6, 18): datetime(2014, 7, 1, 16),
                datetime(2014, 7, 7, 9, 30): datetime(2014, 7, 1, 16, 30),
                datetime(2014, 7, 7, 10, 30, 30):
                datetime(2014, 7, 2, 9, 30, 30),
            },
        ),
        (
            # 5 days and 3 hours later
            BusinessHour(28, start="21:00", end="02:00"),
            {
                datetime(2014, 7, 1, 11): datetime(2014, 7, 9, 0),
                datetime(2014, 7, 1, 22): datetime(2014, 7, 9, 1),
                datetime(2014, 7, 1, 23): datetime(2014, 7, 9, 21),
                datetime(2014, 7, 2, 2): datetime(2014, 7, 10, 0),
                datetime(2014, 7, 3, 21): datetime(2014, 7, 11, 0),
                datetime(2014, 7, 4, 1): datetime(2014, 7, 11, 23),
                datetime(2014, 7, 4, 2): datetime(2014, 7, 12, 0),
                datetime(2014, 7, 4, 3): datetime(2014, 7, 12, 0),
                datetime(2014, 7, 5, 1): datetime(2014, 7, 14, 23),
                datetime(2014, 7, 5, 15): datetime(2014, 7, 15, 0),
                datetime(2014, 7, 6, 18): datetime(2014, 7, 15, 0),
                datetime(2014, 7, 7, 1): datetime(2014, 7, 15, 0),
                datetime(2014, 7, 7, 23, 30): datetime(2014, 7, 15, 21, 30),
            },
        ),
        (
            # large n for multiple opening hours (3 days and 1 hour before)
            BusinessHour(n=-25,
                         start=["09:00", "14:00"],
                         end=["12:00", "19:00"]),
            {
                datetime(2014, 7, 1, 11): datetime(2014, 6, 26, 10),
                datetime(2014, 7, 1, 13): datetime(2014, 6, 26, 11),
                datetime(2014, 7, 1, 9): datetime(2014, 6, 25, 18),
                datetime(2014, 7, 1, 10): datetime(2014, 6, 25, 19),
                datetime(2014, 7, 3, 11): datetime(2014, 6, 30, 10),
                datetime(2014, 7, 3, 8): datetime(2014, 6, 27, 18),
                datetime(2014, 7, 3, 19): datetime(2014, 6, 30, 18),
                datetime(2014, 7, 3, 23): datetime(2014, 6, 30, 18),
                datetime(2014, 7, 4, 9): datetime(2014, 6, 30, 18),
                datetime(2014, 7, 5, 15): datetime(2014, 7, 1, 18),
                datetime(2014, 7, 6, 18): datetime(2014, 7, 1, 18),
                datetime(2014, 7, 7, 9, 30): datetime(2014, 7, 1, 18, 30),
                datetime(2014, 7, 7, 10, 30, 30):
                datetime(2014, 7, 2, 9, 30, 30),
            },
        ),
        (
            # 5 days and 3 hours later
            BusinessHour(28, start=["21:00", "03:00"], end=["01:00", "04:00"]),
            {
                datetime(2014, 7, 1, 11): datetime(2014, 7, 9, 0),
                datetime(2014, 7, 1, 22): datetime(2014, 7, 9, 3),
                datetime(2014, 7, 1, 23): datetime(2014, 7, 9, 21),
                datetime(2014, 7, 2, 2): datetime(2014, 7, 9, 23),
                datetime(2014, 7, 3, 21): datetime(2014, 7, 11, 0),
                datetime(2014, 7, 4, 1): datetime(2014, 7, 11, 23),
                datetime(2014, 7, 4, 2): datetime(2014, 7, 11, 23),
                datetime(2014, 7, 4, 3): datetime(2014, 7, 11, 23),
                datetime(2014, 7, 4, 21): datetime(2014, 7, 12, 0),
                datetime(2014, 7, 5, 0): datetime(2014, 7, 14, 22),
                datetime(2014, 7, 5, 1): datetime(2014, 7, 14, 23),
                datetime(2014, 7, 5, 15): datetime(2014, 7, 14, 23),
                datetime(2014, 7, 6, 18): datetime(2014, 7, 14, 23),
                datetime(2014, 7, 7, 1): datetime(2014, 7, 14, 23),
                datetime(2014, 7, 7, 23, 30): datetime(2014, 7, 15, 21, 30),
            },
        ),
    ]

    @pytest.mark.parametrize("case", apply_large_n_cases)
    def test_apply_large_n(self, case):
        offset, cases = case
        for base, expected in cases.items():
            assert_offset_equal(offset, base, expected)

    def test_apply_nanoseconds(self):
        tests = [
            (
                BusinessHour(),
                {
                    Timestamp("2014-07-04 15:00") + Nano(5):
                    Timestamp("2014-07-04 16:00") + Nano(5),
                    Timestamp("2014-07-04 16:00") + Nano(5):
                    Timestamp("2014-07-07 09:00") + Nano(5),
                    Timestamp("2014-07-04 16:00") - Nano(5):
                    Timestamp("2014-07-04 17:00") - Nano(5),
                },
            ),
            (
                BusinessHour(-1),
                {
                    Timestamp("2014-07-04 15:00") + Nano(5):
                    Timestamp("2014-07-04 14:00") + Nano(5),
                    Timestamp("2014-07-04 10:00") + Nano(5):
                    Timestamp("2014-07-04 09:00") + Nano(5),
                    Timestamp("2014-07-04 10:00") - Nano(5):
                    Timestamp("2014-07-03 17:00") - Nano(5),
                },
            ),
        ]

        for offset, cases in tests:
            for base, expected in cases.items():
                assert_offset_equal(offset, base, expected)

    def test_datetimeindex(self):
        idx1 = date_range(start="2014-07-04 15:00",
                          end="2014-07-08 10:00",
                          freq="BH")
        idx2 = date_range(start="2014-07-04 15:00", periods=12, freq="BH")
        idx3 = date_range(end="2014-07-08 10:00", periods=12, freq="BH")
        expected = DatetimeIndex(
            [
                "2014-07-04 15:00",
                "2014-07-04 16:00",
                "2014-07-07 09:00",
                "2014-07-07 10:00",
                "2014-07-07 11:00",
                "2014-07-07 12:00",
                "2014-07-07 13:00",
                "2014-07-07 14:00",
                "2014-07-07 15:00",
                "2014-07-07 16:00",
                "2014-07-08 09:00",
                "2014-07-08 10:00",
            ],
            freq="BH",
        )
        for idx in [idx1, idx2, idx3]:
            tm.assert_index_equal(idx, expected)

        idx1 = date_range(start="2014-07-04 15:45",
                          end="2014-07-08 10:45",
                          freq="BH")
        idx2 = date_range(start="2014-07-04 15:45", periods=12, freq="BH")
        idx3 = date_range(end="2014-07-08 10:45", periods=12, freq="BH")

        expected = idx1
        for idx in [idx1, idx2, idx3]:
            tm.assert_index_equal(idx, expected)

    def test_bday_ignores_timedeltas(self):
        idx = date_range("2010/02/01", "2010/02/10", freq="12H")
        t1 = idx + BDay(offset=Timedelta(3, unit="H"))

        expected = DatetimeIndex(
            [
                "2010-02-02 03:00:00",
                "2010-02-02 15:00:00",
                "2010-02-03 03:00:00",
                "2010-02-03 15:00:00",
                "2010-02-04 03:00:00",
                "2010-02-04 15:00:00",
                "2010-02-05 03:00:00",
                "2010-02-05 15:00:00",
                "2010-02-08 03:00:00",
                "2010-02-08 15:00:00",
                "2010-02-08 03:00:00",
                "2010-02-08 15:00:00",
                "2010-02-08 03:00:00",
                "2010-02-08 15:00:00",
                "2010-02-09 03:00:00",
                "2010-02-09 15:00:00",
                "2010-02-10 03:00:00",
                "2010-02-10 15:00:00",
                "2010-02-11 03:00:00",
            ],
            freq=None,
        )
        tm.assert_index_equal(t1, expected)