Repository: pandas-dev/pandas

Issue:
Adding offset to DatetimeIndex is broken
#### Code Sample, a copy-pastable example if possible

```python
import pandas as pd
offset = pd.DateOffset(months=3, days=10)
dates = pd.date_range(start='01 Jan 2014', end='01 Jan 2017', freq='AS')
dates + offset
```

#### Problem description

ValueError is raised:

```python

Traceback (most recent call last):
  File "C:\mma\local\Anaconda3\envs\pd24\lib\site-packages\pandas\core\arrays\datetimelike.py", line 884, in _validate_frequency
    raise ValueError
ValueError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\mma\local\Anaconda3\envs\pd24\lib\site-packages\pandas\core\indexes\datetimelike.py", line 489, in __add__
    result = self._data.__add__(maybe_unwrap_index(other))
  File "C:\mma\local\Anaconda3\envs\pd24\lib\site-packages\pandas\core\arrays\datetimelike.py", line 1190, in __add__
    result = self._add_offset(other)
  File "C:\mma\local\Anaconda3\envs\pd24\lib\site-packages\pandas\core\arrays\datetimes.py", line 737, in _add_offset
    result = offset.apply_index(values)
  File "pandas/_libs/tslibs/offsets.pyx", line 116, in pandas._libs.tslibs.offsets.apply_index_wraps.wrapper
  File "C:\mma\local\Anaconda3\envs\pd24\lib\site-packages\pandas\tseries\offsets.py", line 278, in apply_index
    i = type(i)(shifted, freq=i.freq, dtype=i.dtype)
  File "C:\mma\local\Anaconda3\envs\pd24\lib\site-packages\pandas\core\arrays\datetimes.py", line 351, in __init__
    type(self)._validate_frequency(self, freq)
  File "C:\mma\local\Anaconda3\envs\pd24\lib\site-packages\pandas\core\arrays\datetimelike.py", line 897, in _validate_frequency
    .format(infer=inferred, passed=freq.freqstr))
ValueError: Inferred frequency AS-APR from passed values does not conform to passed frequency AS-JAN
```

#### Expected Output

This is what had been working through version 0.22.0 and was broken somewhere between 0.22 and 0.24:

```python
>>> dates + offset
DatetimeIndex(['2014-04-11', '2015-04-11', '2016-04-11', '2017-04-11'], dtype='datetime64[ns]', freq=None)
```
#### Workaround

```python

>>> pd.DatetimeIndex([date + offset for date in dates])
DatetimeIndex(['2014-04-11', '2015-04-11', '2016-04-11', '2017-04-11'], dtype='datetime64[ns]', freq=None)
```

#### Output of ``pd.show_versions()``

<details>

INSTALLED VERSIONS
------------------
commit: None
python: 3.6.8.final.0
python-bits: 64
OS: Windows
OS-release: 7
machine: AMD64
processor: Intel64 Family 6 Model 58 Stepping 9, GenuineIntel
byteorder: little
LC_ALL: None
LANG: None
LOCALE: None.None

pandas: 0.24.2
pytest: 4.4.1
pip: 19.1
setuptools: 41.0.1
Cython: None
numpy: 1.16.3
scipy: None
pyarrow: None
xarray: None
IPython: None
sphinx: None
patsy: None
dateutil: 2.8.0
pytz: 2019.1
blosc: None
bottleneck: None
tables: None
numexpr: None
feather: None
matplotlib: None
openpyxl: None
xlrd: None
xlwt: None
xlsxwriter: None
lxml.etree: None
bs4: None
html5lib: None
sqlalchemy: None
pymysql: None
psycopg2: None
jinja2: None
s3fs: None
fastparquet: None
pandas_gbq: None
pandas_datareader: None
gcsfs: None

</details>



Discussion:
@jbrockmendel is the `freq` supposed to reset to the new inferred freq in case above? 
Yah, it looks like the problem is in tseries.offsets L278 passing `freq=i.freq` to the `type(i)` constructor.

Resolving patch:
diff --git a/pandas/tseries/offsets.py b/pandas/tseries/offsets.py
--- a/pandas/tseries/offsets.py
+++ b/pandas/tseries/offsets.py
@@ -273,7 +273,7 @@ def apply_index(self, i):
                        kwds.get('months', 0)) * self.n)
             if months:
                 shifted = liboffsets.shift_months(i.asi8, months)
-                i = type(i)(shifted, freq=i.freq, dtype=i.dtype)
+                i = type(i)(shifted, dtype=i.dtype)
 
             weeks = (kwds.get('weeks', 0)) * self.n
             if weeks:


Test patch:
diff --git a/pandas/tests/arithmetic/test_datetime64.py b/pandas/tests/arithmetic/test_datetime64.py
--- a/pandas/tests/arithmetic/test_datetime64.py
+++ b/pandas/tests/arithmetic/test_datetime64.py
@@ -1435,6 +1435,28 @@ def test_dt64arr_add_sub_offset_ndarray(self, tz_naive_fixture,
         expected = tm.box_expected(expected, box_with_array)
         tm.assert_equal(res, expected)
 
+    @pytest.mark.parametrize("op, offset, exp", [
+        ('__add__', pd.DateOffset(months=3, days=10),
+         DatetimeIndex([Timestamp('2014-04-11'), Timestamp('2015-04-11'),
+                        Timestamp('2016-04-11'), Timestamp('2017-04-11')])),
+        ('__add__', pd.DateOffset(months=3),
+         DatetimeIndex([Timestamp('2014-04-01'), Timestamp('2015-04-01'),
+                        Timestamp('2016-04-01'), Timestamp('2017-04-01')])),
+        ('__sub__', pd.DateOffset(months=3, days=10),
+         DatetimeIndex([Timestamp('2013-09-21'), Timestamp('2014-09-21'),
+                        Timestamp('2015-09-21'), Timestamp('2016-09-21')])),
+        ('__sub__', pd.DateOffset(months=3),
+         DatetimeIndex([Timestamp('2013-10-01'), Timestamp('2014-10-01'),
+                        Timestamp('2015-10-01'), Timestamp('2016-10-01')]))
+
+    ])
+    def test_dti_add_sub_nonzero_mth_offset(self, op, offset, exp):
+        # GH 26258
+        date = date_range(start='01 Jan 2014', end='01 Jan 2017', freq='AS')
+        mth = getattr(date, op)
+        result = mth(offset)
+        tm.assert_equal(result, exp)
+
 
 class TestDatetime64OverflowHandling:
     # TODO: box + de-duplicate