Skip to content

BUG: Fix creating DatetimeIndex with BusinessHour Frequency #50530

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
2 changes: 1 addition & 1 deletion doc/source/whatsnew/v1.5.3.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Bug fixes
- Bug in :meth:`.Styler.to_excel` leading to error when unrecognized ``border-style`` (e.g. ``"hair"``) provided to Excel writers (:issue:`48649`)
- Bug when chaining several :meth:`.Styler.concat` calls, only the last styler was concatenated (:issue:`49207`)
- Fixed bug when instantiating a :class:`DataFrame` subclass inheriting from ``typing.Generic`` that triggered a ``UserWarning`` on python 3.11 (:issue:`49649`)
-
- Fixed bug in :class:`BusinessHour` that could cause creation of ``DatetimeIndex`` to fail (:issue:`#49835`)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Fixed bug in :class:`BusinessHour` that could cause creation of ``DatetimeIndex`` to fail (:issue:`#49835`)
- Fixed bug in :class:`BusinessHour` that could cause creation of :class:`DatetimeIndex` to fail (:issue:`49835`)
  1. Could you move this to v2.0.0.rst?
  2. Could you make this description more specific too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've written it like this now, is that ok?
- Bug in :class:`BusinessHour` would cause creation of :class:`DatetimeIndex` to fail when no opening hour was included in the index (:issue:`#49835`)

Thanks for reviewing!


.. ---------------------------------------------------------------------------
.. _whatsnew_153.other:
Expand Down
9 changes: 7 additions & 2 deletions pandas/_libs/tslibs/offsets.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -1847,15 +1847,20 @@ cdef class BusinessHour(BusinessMixin):
earliest_start = self.start[0]
latest_start = self.start[-1]

if self.n == 0:
is_same_sign = sign > 0
else:
is_same_sign = self.n * sign >= 0

if not self.next_bday.is_on_offset(other):
# today is not business day
other = other + sign * self.next_bday
if self.n * sign >= 0:
if is_same_sign:
hour, minute = earliest_start.hour, earliest_start.minute
else:
hour, minute = latest_start.hour, latest_start.minute
else:
if self.n * sign >= 0:
if is_same_sign:
if latest_start < other.time():
# current time is after latest starting time in today
other = other + sign * self.next_bday
Expand Down
9 changes: 8 additions & 1 deletion pandas/tests/tseries/offsets/test_business_hour.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,9 @@ def test_add_datetime(
assert offset8 + dt == datetime(2014, 7, 1, 11)
assert offset9 + dt == datetime(2014, 7, 1, 22)
assert offset10 + dt == datetime(2014, 7, 1, 1)
assert dt + 0 * offset1 == dt

def test_sub(self, dt, offset2, _offset):
def test_sub(self, dt, offset1, offset2, _offset):
off = offset2
msg = "Cannot subtract datetime from offset"
with pytest.raises(TypeError, match=msg):
Expand All @@ -241,6 +242,8 @@ def test_sub(self, dt, offset2, _offset):

assert dt - offset2 == dt + _offset(-3)

assert dt - 0 * offset1 == dt

def testRollback1(
self,
dt,
Expand Down Expand Up @@ -972,6 +975,10 @@ def test_datetimeindex(self):
for idx in [idx1, idx2, idx3]:
tm.assert_index_equal(idx, expected)

idx4 = date_range(start="2014-07-01 10:00", freq="BH", periods=1)
expected4 = DatetimeIndex(["2014-07-01 10:00"], freq="BH")
tm.assert_index_equal(idx4, expected4)

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"))
Expand Down