diff --git a/doc/source/whatsnew/v2.0.0.rst b/doc/source/whatsnew/v2.0.0.rst index 13b60f7f05352..c35a0abb3a389 100644 --- a/doc/source/whatsnew/v2.0.0.rst +++ b/doc/source/whatsnew/v2.0.0.rst @@ -881,6 +881,7 @@ Indexing - Bug in :func:`~DataFrame.describe` when formatting percentiles in the resulting index showed more decimals than needed (:issue:`46362`) - Bug in :meth:`DataFrame.compare` does not recognize differences when comparing ``NA`` with value in nullable dtypes (:issue:`48939`) - Bug in :meth:`DataFrame.isetitem` coercing extension array dtypes in :class:`DataFrame` to object (:issue:`49922`) +- Bug in :class:`BusinessHour` would cause creation of :class:`DatetimeIndex` to fail when no opening hour was included in the index (:issue:`49835`) - Missing diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index 0bc9751694e9f..b59d17321d8bf 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -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 diff --git a/pandas/tests/tseries/offsets/test_business_hour.py b/pandas/tests/tseries/offsets/test_business_hour.py index 79e7a5ff67010..319cc053d5d7d 100644 --- a/pandas/tests/tseries/offsets/test_business_hour.py +++ b/pandas/tests/tseries/offsets/test_business_hour.py @@ -241,6 +241,12 @@ def test_sub(self, dt, offset2, _offset): assert dt - offset2 == dt + _offset(-3) + def test_multiply_by_zero(self, dt, offset1, offset2): + assert dt - 0 * offset1 == dt + assert dt + 0 * offset1 == dt + assert dt - 0 * offset2 == dt + assert dt + 0 * offset2 == dt + def testRollback1( self, dt, @@ -972,6 +978,12 @@ def test_datetimeindex(self): for idx in [idx1, idx2, idx3]: tm.assert_index_equal(idx, expected) + def test_short_datetimeindex_creation(self): + # gh-49835 + 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"))