1

I am on pandas version 1.1.3.

Suppose I have the following index

import pandas as pd
from pandas.tseries.offsets import CDay

idx = pd.bdate_range("2010-02-03","2010-02-12") + pd.Timedelta('22H')

If I then add:

shifted_idx = idx + 0*CDay(offset=pd.Timedelta('4H'))

I would expect the timestamp in idx of 2010-05-05 22:00 to move to 2010-05-08 02:00 since CDay() has weekmask = ‘Mon Tue Wed Thu Fri’ by default.

However, we see in shifted_idx a timestamp 2010-02-06 02:00:00 which is on a Saturday and violates the weekmask?

mch56
  • 742
  • 6
  • 24
  • @mhc56 since the bounty expires tomorrow, it would be awesome if you could take a look at my answer and give your feedback ;). – Qusai Alothman Dec 03 '20 at 14:17

2 Answers2

2

The offset parameter is applied after the day shift is applied, that's why you are getting these results.

You can see that by taking a look at the source code of the apply method of the CustomBusinessDay class. Note that CDay is just an alias of CustomBusinessDay.

Not sure if this counts as a bug, because you can argue that this is the intended behavior. I couldn't find any documentation to support nor oppose this.

For now, you can work around this by manually applying the offset first, then applying the mask. Something like this:

idx_hours_offset = idx + pd.Timedelta('4H')                                          

shifted_idx = idx_hours_offset + 0*CDay()
Qusai Alothman
  • 1,982
  • 9
  • 23
  • 1
    Ah okay, this explains it then. Nice to know. I guess the documentation should be a bit more verbose about this – mch56 Dec 03 '20 at 19:08
-1

By typing shifted_idx = idx + 0*CDay(offset=pd.Timedelta('4H')) you just add 4h to the previous timestamp, the CDay thingy doesn't work there.

It's much simpler to do a normal pd.date_range and add the four hours to that range and finally slice the dataframe using the following code:

    import pandas as pd
    idx = pd.date_range("2010-02-03","2010-02-12") + pd.Timedelta('22H')
    shifted_idx = idx + pd.Timedelta('4H')
    shifted_idx = shifted_idx[shifted_idx.dayofweek < 5]
Dharman
  • 30,962
  • 25
  • 85
  • 135
Amun_Re
  • 136
  • 6
  • This method won't work if I want to include a custom calendar, which is why `CDay` is appealing – mch56 Nov 27 '20 at 16:59