Skip to content

BUG: date_range closed keyword with timezone aware start/end (GH12684) #13510

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/source/whatsnew/v0.18.1.txt
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ Bug Fixes
- Bug in ``CategoricalIndex.get_loc`` returns different result from regular ``Index`` (:issue:`12531`)
- Bug in ``PeriodIndex.resample`` where name not propagated (:issue:`12769`)


- Bug in ``date_range`` ``closed`` keyword and timezones (:issue:`12684`).

- Bug in ``pd.concat`` raises ``AttributeError`` when input data contains tz-aware datetime and timedelta (:issue:`12620`)
- Bug in ``pd.concat`` did not handle empty ``Series`` properly (:issue:`11082`)
Expand Down
7 changes: 7 additions & 0 deletions pandas/tseries/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
35 changes: 24 additions & 11 deletions pandas/tseries/tests/test_daterange.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed this test, as I think it is testing the wrong behaviour (it tests that the different closed options give all the same result, which should not be (and is not the case with naive timestamps))

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
Expand Down