TST: add tests for DatetimeIndex.is_year_start/is_quarter_start on "BMS" frequency
State: closed

- [x] closes #58729
- [x] Tests added and passed
- [x] Added an entry in the latest `doc/source/whatsnew/v3.0.0.rst

Labels:
name: Testing
description: pandas testing functions or related to the test suite
name: Frequency
description: DateOffsets

Comments:
Thanks @natmokval for the PR.

Should the OP be an issue instead.? or is there already an open issue for this?
> Should the OP be an issue instead.? or is there already an open issue for this?
>

thanks @simonjayhawkins for the comment. No, there is no open issue for this.
It's my mistake; I should have opened an issue first. Now I've opened the issue for this PR.
Fixed bug in `DatetimeIndex.is_year_start` and `DatetimeIndex.is_quarter_start` returning `False` instead of `True` when using BusinessMonthBegin frequency. @MarcoGorelli, could you please take a look at this PR?
thanks for looking into this

not sure this fixes the issue to be honest:
```python
In [2]: pd.DatetimeIndex(['1976-11-01', '1976-12-01', '1977-01-03'], freq='BMS')
Out[2]: DatetimeIndex(['1976-11-01', '1976-12-01', '1977-01-03'], dtype='datetime64[s]', freq='BMS')

In [3]: arr = pd.DatetimeIndex(['1976-11-01', '1976-12-01', '1977-01-03'], freq='BMS')

In [4]: arr.is_year_start
Out[4]: array([False, False,  True])

In [5]: [x.is_year_start for x in arr]
Out[5]: [False, False, False]
```
We'd expect `Out[4]` and `Out[5]` to be the same, right?

Here's a little hypothesis test I put together:
```python
import pytest
import hypothesis.strategies as st
from hypothesis import given
import pandas as pd
from datetime import datetime


@pytest.mark.parametrize('freq', [
    'MS',
    'BMS',
])
@given(dt = st.datetimes(min_value=datetime(1960, 1, 1), max_value=datetime(1980, 1, 1)))
def test_me(freq, dt):
    d = pd.date_range(dt, periods=3, freq=freq)
    result = [x for x in d.is_year_start]
    expected = [x.is_year_start for x in d]
    assert result == expected
```

Granted, it looks like this is already super-broken on `main` anyway, but I think this requires a more general and a very careful and focused fix
Sorry, as an addendum to my previous comment: `Timestamp` doesn't have `freq`, so the two results can't be expected to be the same

If I amend the hypothesis test to be:
```python
@given(
    dt = st.datetimes(min_value=datetime(1960, 1, 1), max_value=datetime(1980, 1, 1)),
    n = st.integers(min_value=1, max_value=10),
    freq = st.sampled_from(['BMS'])
)
def test_me(freq, dt, n):
    freq = f'{n}{freq}'
    d = pd.date_range(dt, periods=3, freq=freq)
    result = [x for x in d.is_year_start]
    expected = []
    for x in d:
        if x.is_year_start:
            expected.append(True)
        else:
            if x.day_of_week == 0 and (x - pd.Timedelta(days=1)).is_year_start:
                expected.append(True)
            elif x.day_of_week == 0 and (x - pd.Timedelta(days=2)).is_year_start:
                expected.append(True)
            else:
                expected.append(False)
    assert result == expected
```
then it does indeed pass

I think we should get https://github.com/pandas-dev/pandas/pull/57494 in first though, as I think that that also fixes the issues "for free" (but then we keep the test from this one)
 > I think we should get #57494 in first though, as I think that that also fixes the issues "for free" (but then we keep the test from this one)
>
thanks, I will update this PR after we get the #57494 in.

@MarcoGorelli, I updated this PR, could you please take a look at my changes?