Repository: pandas-dev/pandas

Issue:
Regression: date_range closed parameter not honoured in pandas 0.18.0
The behaviour of the method [date_range](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.date_range.html) appears to have changed between version 17 and 19. the below example changes the starting bound of the index returned?

`print pd.date_range(start=datetime.datetime(2016,3,18,0,0), end=datetime.datetime(2016,3,22,0,0), freq='D', tz='UTC', closed='right')`

**pandas 0.17.0 Output**
DatetimeIndex(['2016-03-19', '2016-03-20', '2016-03-21', '2016-03-22'], dtype='datetime64[ns, UTC]', freq='D')

**pandas 0.18.0 Output**
DatetimeIndex(['2016-03-18', '2016-03-19', '2016-03-20', '2016-03-21', '2016-03-22'],
              dtype='datetime64[ns, UTC]', freq='D')

python: 2.7.11.final.0



Discussion:
this was originally this issue: https://github.com/pydata/pandas/issues/11804
and fixed here: https://github.com/pydata/pandas/pull/11806 and #12410 

yeah this coerces to the basic data (i8) right before the closed detection which is incorrect.

pull-requests welcome!

cc @hcontrast 
cc @thrasibule

right about [here](https://github.com/pydata/pandas/blob/master/pandas/tseries/index.py#L531)

Okay thanks, I'll keep an eye out for the fix.

@PH82 if you'd like to submit a patch would be helpful.


Resolving patch:
diff --git a/pandas/tseries/index.py b/pandas/tseries/index.py
--- a/pandas/tseries/index.py
+++ b/pandas/tseries/index.py
@@ -541,6 +541,13 @@ def _generate(cls, start, end, periods, name, offset,
                                                  ambiguous=ambiguous)
                 index = index.view(_NS_DTYPE)
 
+                # index is localized datetime64 array -> have to convert
+                # start/end as well to compare
+                if start is not None:
+                    start = start.tz_localize(tz).asm8
+                if end is not None:
+                    end = end.tz_localize(tz).asm8
+
         if not left_closed and len(index) and index[0] == start:
             index = index[1:]
         if not right_closed and len(index) and index[-1] == end:


Test patch:
diff --git a/pandas/tseries/tests/test_daterange.py b/pandas/tseries/tests/test_daterange.py
--- a/pandas/tseries/tests/test_daterange.py
+++ b/pandas/tseries/tests/test_daterange.py
@@ -485,7 +485,7 @@ def test_range_closed(self):
         begin = datetime(2011, 1, 1)
         end = datetime(2014, 1, 1)
 
-        for freq in ["3D", "2M", "7W", "3H", "A"]:
+        for freq in ["1D", "3D", "2M", "7W", "3H", "A"]:
             closed = date_range(begin, end, closed=None, freq=freq)
             left = date_range(begin, end, closed="left", freq=freq)
             right = date_range(begin, end, closed="right", freq=freq)
@@ -501,11 +501,11 @@ def test_range_closed(self):
             self.assert_index_equal(expected_right, right)
 
     def test_range_closed_with_tz_aware_start_end(self):
-        # GH12409
+        # GH12409, GH12684
         begin = Timestamp('2011/1/1', tz='US/Eastern')
         end = Timestamp('2014/1/1', tz='US/Eastern')
 
-        for freq in ["3D", "2M", "7W", "3H", "A"]:
+        for freq in ["1D", "3D", "2M", "7W", "3H", "A"]:
             closed = date_range(begin, end, closed=None, freq=freq)
             left = date_range(begin, end, closed="left", freq=freq)
             right = date_range(begin, end, closed="right", freq=freq)
@@ -520,15 +520,28 @@ def test_range_closed_with_tz_aware_start_end(self):
             self.assert_index_equal(expected_left, left)
             self.assert_index_equal(expected_right, right)
 
-        # test with default frequency, UTC
-        begin = Timestamp('2011/1/1', tz='UTC')
-        end = Timestamp('2014/1/1', tz='UTC')
+        begin = Timestamp('2011/1/1')
+        end = Timestamp('2014/1/1')
+        begintz = Timestamp('2011/1/1', tz='US/Eastern')
+        endtz = Timestamp('2014/1/1', tz='US/Eastern')
+
+        for freq in ["1D", "3D", "2M", "7W", "3H", "A"]:
+            closed = date_range(begin, end, closed=None, freq=freq,
+                                tz='US/Eastern')
+            left = date_range(begin, end, closed="left", freq=freq,
+                              tz='US/Eastern')
+            right = date_range(begin, end, closed="right", freq=freq,
+                               tz='US/Eastern')
+            expected_left = left
+            expected_right = right
 
-        intervals = ['left', 'right', None]
-        for i in intervals:
-            result = date_range(start=begin, end=end, closed=i)
-            self.assertEqual(result[0], begin)
-            self.assertEqual(result[-1], end)
+            if endtz == closed[-1]:
+                expected_left = closed[:-1]
+            if begintz == closed[0]:
+                expected_right = closed[1:]
+
+            self.assert_index_equal(expected_left, left)
+            self.assert_index_equal(expected_right, right)
 
     def test_range_closed_boundary(self):
         # GH 11804