Repository: pandas-dev/pandas

Issue:
pandas.DataFrame.resample  behaves inconsistently when the rule is set to 24H/1D and 48H/2D
#### Code Sample, a copy-pastable example if possible

```python
>>> pd.__version__
'0.23.4'
>>> index = pd.date_range('11/11/2000 06:00:00', periods=50, freq='H')
>>> series = pd.Series(range(50), index=index)
>>> series.head(10)
2000-11-11 06:00:00    0
2000-11-11 07:00:00    1
2000-11-11 08:00:00    2
2000-11-11 09:00:00    3
2000-11-11 10:00:00    4
2000-11-11 11:00:00    5
2000-11-11 12:00:00    6
2000-11-11 13:00:00    7
2000-11-11 14:00:00    8
2000-11-11 15:00:00    9
Freq: H, dtype: int64
>>> series.resample('24H').count()
2000-11-11    18
2000-11-12    24
2000-11-13     8
Freq: 24H, dtype: int64
>>> series.resample('1D').count()
2000-11-11    18
2000-11-12    24
2000-11-13     8
Freq: D, dtype: int64
>>> series.resample('48H').count()
2000-11-11    42
2000-11-13     8
Freq: 48H, dtype: int64
>>> series.resample('2D').count()
2000-11-11 06:00:00    48
2000-11-13 06:00:00     2
dtype: int64

```
#### Problem description

As you can see, when I set rule to '24H' or '1D', the behavior of resample is consistent (in both cases it starts at 0 o'clock on the first day), but for '48H' and '2D' it's obviously not.

#### Expected Output
If the behavior consistency of ‘24H’ and ‘1D’ is correct, then the behaviors of '48H' and '2D' should also be consistent.
#### Output of ``pd.show_versions()``

<details>

commit: None
python: 3.6.6.final.0
python-bits: 64
OS: Windows
OS-release: 10
machine: AMD64
processor: Intel64 Family 6 Model 158 Stepping 9, GenuineIntel
byteorder: little
LC_ALL: None
LANG: None
LOCALE: None.None
pandas: 0.23.4
pytest: None
pip: 18.1
setuptools: 40.4.3
Cython: None
numpy: 1.15.2
scipy: 1.1.0
pyarrow: None
xarray: None
IPython: None
sphinx: None
patsy: None
dateutil: 2.7.3
pytz: 2018.5
blosc: None
bottleneck: None
tables: None
numexpr: None
feather: None
matplotlib: None
openpyxl: None
xlrd: None
xlwt: None
xlsxwriter: None
lxml: None
bs4: None
html5lib: None
sqlalchemy: None
pymysql: None
psycopg2: None
jinja2: None
s3fs: None
fastparquet: None
pandas_gbq: None
pandas_datareader: None

</details>



Discussion:
Seems the issue is in `pandas.core.resample._get_range_edges`, line 1591.

I think `day_nanos % offset.nanos == 0` should be the other way around. This will only ever evaluate to True for Day(n=1). I’m guessing this wasn’t the inention as it would be overly complicated compared to `day_nanos == offset.nanos`.

Resolving patch:
diff --git a/pandas/core/resample.py b/pandas/core/resample.py
--- a/pandas/core/resample.py
+++ b/pandas/core/resample.py
@@ -1587,8 +1587,8 @@ def _get_range_edges(first, last, offset, closed='left', base=0):
         is_day = isinstance(offset, Day)
         day_nanos = delta_to_nanoseconds(timedelta(1))
 
-        # #1165
-        if (is_day and day_nanos % offset.nanos == 0) or not is_day:
+        # #1165 and #24127
+        if (is_day and not offset.nanos % day_nanos) or not is_day:
             return _adjust_dates_anchored(first, last, offset,
                                           closed=closed, base=base)
 


Test patch:
diff --git a/pandas/tests/groupby/test_timegrouper.py b/pandas/tests/groupby/test_timegrouper.py
--- a/pandas/tests/groupby/test_timegrouper.py
+++ b/pandas/tests/groupby/test_timegrouper.py
@@ -43,8 +43,8 @@ def test_groupby_with_timegrouper(self):
 
             expected = DataFrame(
                 {'Quantity': 0},
-                index=date_range('20130901 13:00:00',
-                                 '20131205 13:00:00', freq='5D',
+                index=date_range('20130901',
+                                 '20131205', freq='5D',
                                  name='Date', closed='left'))
             expected.iloc[[0, 6, 18], 0] = np.array([24, 6, 9], dtype='int64')
 
diff --git a/pandas/tests/resample/test_datetime_index.py b/pandas/tests/resample/test_datetime_index.py
--- a/pandas/tests/resample/test_datetime_index.py
+++ b/pandas/tests/resample/test_datetime_index.py
@@ -1463,3 +1463,29 @@ def f(data, add_arg):
         result = df.groupby("A").resample("D").agg(f, multiplier)
         expected = df.groupby("A").resample('D').mean().multiply(multiplier)
         assert_frame_equal(result, expected)
+
+    @pytest.mark.parametrize('k', [1, 2, 3])
+    @pytest.mark.parametrize('n1, freq1, n2, freq2', [
+        (30, 'S', 0.5, 'Min'),
+        (60, 'S', 1, 'Min'),
+        (3600, 'S', 1, 'H'),
+        (60, 'Min', 1, 'H'),
+        (21600, 'S', 0.25, 'D'),
+        (86400, 'S', 1, 'D'),
+        (43200, 'S', 0.5, 'D'),
+        (1440, 'Min', 1, 'D'),
+        (12, 'H', 0.5, 'D'),
+        (24, 'H', 1, 'D'),
+    ])
+    def test_resample_equivalent_offsets(self, n1, freq1, n2, freq2, k):
+        # GH 24127
+        n1_ = n1 * k
+        n2_ = n2 * k
+        s = pd.Series(0, index=pd.date_range('19910905 13:00',
+                                             '19911005 07:00',
+                                             freq=freq1))
+        s = s + range(len(s))
+
+        result1 = s.resample(str(n1_) + freq1).mean()
+        result2 = s.resample(str(n2_) + freq2).mean()
+        assert_series_equal(result1, result2)