ENH: Add BusinessHour offset by sinhrks · Pull Request #7905 · pandas-dev/pandas (original) (raw)

Closes #2469. Create BusinessHour offset to specify business hours on BusinessDay. Appreciated if any feedbacks regarding bahaviours, keywords, etc.

Basic

By default, use 9:00 - 17:00 as business hours. Adding BusinessHour will increment timestamp by hourly on the days belong to BusinessDay offset.

bh = pd.offsets.BusinessHour()
repr(bh)
# <BusinessHour: BH=09:00-17:00>

pd.Timestamp('2014-08-01 10:00') + bh
#2014-08-01 11:00:00
pd.Timestamp('2014-08-01 08:00') + bh
#2014-08-01 10:00:00

# move to next Business Day
pd.Timestamp('2014-08-01 19:00') + bh
#2014-08-04 10:00:00

# if exceeds the closing time, remaining are added to next day
pd.Timestamp('2014-08-01 16:45') + bh
#2014-08-04 09:45:00

# if n != 1
pd.Timestamp('2014-08-01 10:00') + pd.offsets.BusinessHour(2)
#2014-08-01 12:00:00

pd.Timestamp('2014-08-01 10:00') + pd.offsets.BusinessHour(-3)
#2014-07-31 15:00:00

# Create Index
pd.date_range('2014-07-08 10:00', freq='BH', periods=40)
# [2014-07-08 10:00:00, ..., 2014-07-14 17:00:00]
# Length: 40, Freq: BH, Timezone: None

Specify Opening/Closing Hour

Allow to specify opening/closing time using start and end keyword by hour:minute string or datetime.time.

bh = pd.offsets.BusinessHour(start='11:00', end=datetime.time(20, 0))
repr(bh)
# <BusinessHour: BH=11:00-20:00>

pd.Timestamp('2014-08-01 10:00') + bh
#2014-08-01 12:00:00
pd.Timestamp('2014-08-01 13:00') + bh
#2014-08-01 14:00:00
pd.Timestamp('2014-08-01 19:00') + bh
#2014-08-04 11:00:00

# if end < start, it will be midnight business hour
bh = pd.offsets.BusinessHour(start='17:00', end='9:00')
repr(bh)
# <BusinessHour: BH=17:00-09:00>

pd.Timestamp('2014-07-31 10:00') + bh
#2014-07-31 18:00:00
pd.Timestamp('2014-07-31 23:00') + bh
#2014-08-01 00:00:00
pd.Timestamp('2014-07-31 01:00') + bh
#2014-07-31 02:00:00
pd.Timestamp('2014-08-01 13:00') + bh
#2014-08-01 18:00:00

Edge cases

onOffset should include both edges.

pd.offsets.BusinessHour().onOffset(pd.Timestamp('2014-08-01 09:00'))
# True

pd.offsets.BusinessHour().onOffset(pd.Timestamp('2014-08-01 17:00'))
# True

If result is on the end-edge of business hour, move to next

# not 2014-08-01 17:00
pd.Timestamp('2014-08-01 16:00') + pd.offsets.BusinessHour()
#2014-08-04 09:00

# not 2014-08-01 09:00
pd.Timestamp('2014-08-01 10:00') - pd.offsets.BusinessHour()
#2014-07:31 17:00

In case of midnight business hour, distinguish the date by its opening hour

#2014-08-02 is Saturday, but handled as valid because its business hour starts on 08-01
pd.Timestamp('2014-08-02 01:00') + pd.offsets.BusinessHour(start='17:00', end='9:00')
#2014-08:02 02:00

Remainings: