BUG: fix infer frequency for business daily
State: closed

Closes #16624 

Had to update a couple of tests, test_timedelta and test_business_daily, which appear to rely on the old incorrect behaviour. Added a new regression test, test_business_daily_look_alike, for the bug.

Modest performance impact: for 50,000-long business daily index, infer_freq goes from 2.54 ms to 3.91 ms. There should be no performance impact in most cases for non-business daily index, as the initial day_deltas check will throw out most of these cases.

Labels:
name: Bug
name: Frequency
description: DateOffsets
name: Resample
description: resample method

Comments:
# [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/16683?src=pr&el=h1) Report
> Merging [#16683](https://codecov.io/gh/pandas-dev/pandas/pull/16683?src=pr&el=desc) into [master](https://codecov.io/gh/pandas-dev/pandas/commit/b72519e45bbfe7387e0c576c9315475aace69a2b?src=pr&el=desc) will **decrease** coverage by `<.01%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/pandas-dev/pandas/pull/16683/graphs/tree.svg?token=eZ4WkYLtcO&src=pr&height=150&width=650)](https://codecov.io/gh/pandas-dev/pandas/pull/16683?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master   #16683      +/-   ##
==========================================
- Coverage   90.95%   90.94%   -0.01%     
==========================================
  Files         161      161              
  Lines       49272    49280       +8     
==========================================
+ Hits        44815    44820       +5     
- Misses       4457     4460       +3
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `88.71% <100%> (-0.01%)` | :arrow_down: |
| #single | `40.23% <100%> (ø)` | :arrow_up: |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/16683?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/tseries/frequencies.py](https://codecov.io/gh/pandas-dev/pandas/pull/16683?src=pr&el=tree#diff-cGFuZGFzL3RzZXJpZXMvZnJlcXVlbmNpZXMucHk=) | `96.08% <100%> (+0.05%)` | :arrow_up: |
| [pandas/plotting/\_timeseries.py](https://codecov.io/gh/pandas-dev/pandas/pull/16683?src=pr&el=tree#diff-cGFuZGFzL3Bsb3R0aW5nL190aW1lc2VyaWVzLnB5) | `60.2% <0%> (-1.58%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/16683?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/16683?src=pr&el=footer). Last update [b72519e...310d412](https://codecov.io/gh/pandas-dev/pandas/pull/16683?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

# [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/16683?src=pr&el=h1) Report
> Merging [#16683](https://codecov.io/gh/pandas-dev/pandas/pull/16683?src=pr&el=desc) into [master](https://codecov.io/gh/pandas-dev/pandas/commit/b72519e45bbfe7387e0c576c9315475aace69a2b?src=pr&el=desc) will **increase** coverage by `0.01%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/pandas-dev/pandas/pull/16683/graphs/tree.svg?height=150&width=650&token=eZ4WkYLtcO&src=pr)](https://codecov.io/gh/pandas-dev/pandas/pull/16683?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master   #16683      +/-   ##
==========================================
+ Coverage   90.95%   90.96%   +0.01%     
==========================================
  Files         161      161              
  Lines       49272    49299      +27     
==========================================
+ Hits        44815    44847      +32     
+ Misses       4457     4452       -5
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `88.74% <100%> (+0.02%)` | :arrow_up: |
| #single | `40.17% <100%> (-0.05%)` | :arrow_down: |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/16683?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/tseries/frequencies.py](https://codecov.io/gh/pandas-dev/pandas/pull/16683?src=pr&el=tree#diff-cGFuZGFzL3RzZXJpZXMvZnJlcXVlbmNpZXMucHk=) | `96.08% <100%> (+0.05%)` | :arrow_up: |
| [pandas/io/common.py](https://codecov.io/gh/pandas-dev/pandas/pull/16683?src=pr&el=tree#diff-cGFuZGFzL2lvL2NvbW1vbi5weQ==) | `67.79% <0%> (-2.12%)` | :arrow_down: |
| [pandas/plotting/\_timeseries.py](https://codecov.io/gh/pandas-dev/pandas/pull/16683?src=pr&el=tree#diff-cGFuZGFzL3Bsb3R0aW5nL190aW1lc2VyaWVzLnB5) | `60.2% <0%> (-1.58%)` | :arrow_down: |
| [pandas/io/pytables.py](https://codecov.io/gh/pandas-dev/pandas/pull/16683?src=pr&el=tree#diff-cGFuZGFzL2lvL3B5dGFibGVzLnB5) | `92.87% <0%> (-0.17%)` | :arrow_down: |
| [pandas/core/indexing.py](https://codecov.io/gh/pandas-dev/pandas/pull/16683?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvaW5kZXhpbmcucHk=) | `93.92% <0%> (-0.09%)` | :arrow_down: |
| [pandas/core/categorical.py](https://codecov.io/gh/pandas-dev/pandas/pull/16683?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvY2F0ZWdvcmljYWwucHk=) | `95.46% <0%> (-0.05%)` | :arrow_down: |
| [pandas/core/groupby.py](https://codecov.io/gh/pandas-dev/pandas/pull/16683?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvZ3JvdXBieS5weQ==) | `92.07% <0%> (-0.01%)` | :arrow_down: |
| [pandas/core/indexes/datetimes.py](https://codecov.io/gh/pandas-dev/pandas/pull/16683?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvaW5kZXhlcy9kYXRldGltZXMucHk=) | `95.33% <0%> (ø)` | :arrow_up: |
| [pandas/core/series.py](https://codecov.io/gh/pandas-dev/pandas/pull/16683?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvc2VyaWVzLnB5) | `94.9% <0%> (ø)` | :arrow_up: |
| [pandas/io/stata.py](https://codecov.io/gh/pandas-dev/pandas/pull/16683?src=pr&el=tree#diff-cGFuZGFzL2lvL3N0YXRhLnB5) | `93.47% <0%> (ø)` | :arrow_up: |
| ... and [21 more](https://codecov.io/gh/pandas-dev/pandas/pull/16683?src=pr&el=tree-more) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/16683?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/16683?src=pr&el=footer). Last update [b72519e...6042aa4](https://codecov.io/gh/pandas-dev/pandas/pull/16683?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

@jreback ASV report 
[attached](https://github.com/pandas-dev/pandas/files/1068792/asv_report.txt), indicates that no benchmarks are significantly changed.

@jreback are you OK with the changes here? LGTM on a quick skim.
can you update
On the suggestion of @jreback, I have made the test_timedelta unit test cover both 'B' and 'D' frequencies, and have expanded the ASV tests for infer_freq.

Note the unit test in master is actually /wrong/: it asserts that `shifted.freq == index.freq`, which should not hold if index has `freq == 'B'`. This was my original reason for changing freq to 'D' in the test case. I now omit this aspect of the test when `freq == 'B'`, but perform the rest of the test.

The ASV test shows no change in performance when the inferred frequency is daily. There is a 50% slow-down when the inferred frequency is business daily, which is in line with the benchmark I submitted originally with this pull request, and I think is justifiable given the additional checks taking place.

More surprising, perhaps, is that time_infer_freq_none (in my commit; time_infer_freq in master) has a 124% slowdown. However, I think this result is misleading. Note the test case self.no_freq (in master: self.a) actually triggers the bug this PR request solves! So in master, it will wrongly return an inferred frequency of business daily, short-circuiting the tests. By contrast, in this branch it must go both through the whole of _is_business_daily (since it passes the initial 'quick check' on day deltas), and _get_wom_rule. It is therefore a worst case example for this branch, and does 'better than it should' (because of the bug) in master.
looks like a tiny lint error.
thanks!