diff --git a/doc/source/whatsnew/v0.23.0.txt b/doc/source/whatsnew/v0.23.0.txt index c6991bc016868..6f5c180c587bd 100644 --- a/doc/source/whatsnew/v0.23.0.txt +++ b/doc/source/whatsnew/v0.23.0.txt @@ -525,7 +525,7 @@ Other Enhancements library. (:issue:`20564`) - Added new writer for exporting Stata dta files in version 117, ``StataWriter117``. This format supports exporting strings with lengths up to 2,000,000 characters (:issue:`16450`) - :func:`to_hdf` and :func:`read_hdf` now accept an ``errors`` keyword argument to control encoding error handling (:issue:`20835`) -- :func:`date_range` now returns a linearly spaced ``DatetimeIndex`` if ``start``, ``stop``, and ``periods`` are specified, but ``freq`` is not. (:issue:`20808`) +- :func:`date_range` now returns a linearly spaced ``DatetimeIndex`` if ``start``, ``stop``, and ``periods`` are specified, but ``freq`` is not. (:issue:`20808`, :issue:`20983`) .. _whatsnew_0230.api_breaking: diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py index 1b5aa3b45f3b5..1d5c2d9a098ed 100644 --- a/pandas/core/indexes/datetimes.py +++ b/pandas/core/indexes/datetimes.py @@ -587,10 +587,13 @@ def _generate(cls, start, end, periods, name, freq, if end is not None: end = end.tz_localize(tz).asm8 else: + # Create a linearly spaced date_range in local time + start = start.tz_localize(tz) + end = end.tz_localize(tz) index = tools.to_datetime(np.linspace(start.value, - end.value, periods)) - if tz is not None: - index = index.tz_localize('UTC').tz_convert(tz) + end.value, periods), + utc=True) + index = index.tz_convert(tz) if not left_closed and len(index) and index[0] == start: index = index[1:] diff --git a/pandas/tests/indexes/datetimes/test_date_range.py b/pandas/tests/indexes/datetimes/test_date_range.py index bbe9cb65eb1a9..3fb088329f225 100644 --- a/pandas/tests/indexes/datetimes/test_date_range.py +++ b/pandas/tests/indexes/datetimes/test_date_range.py @@ -164,20 +164,39 @@ def test_date_range_ambiguous_arguments(self): def test_date_range_convenience_periods(self): # GH 20808 - rng = date_range('2018-04-24', '2018-04-27', periods=3) - exp = DatetimeIndex(['2018-04-24 00:00:00', '2018-04-25 12:00:00', - '2018-04-27 00:00:00'], freq=None) + result = date_range('2018-04-24', '2018-04-27', periods=3) + expected = DatetimeIndex(['2018-04-24 00:00:00', + '2018-04-25 12:00:00', + '2018-04-27 00:00:00'], freq=None) - tm.assert_index_equal(rng, exp) + tm.assert_index_equal(result, expected) # Test if spacing remains linear if tz changes to dst in range - rng = date_range('2018-04-01 01:00:00', '2018-04-01 04:00:00', - tz='Australia/Sydney', periods=3) - exp = DatetimeIndex(['2018-04-01 01:00:00+11:00', - '2018-04-01 02:00:00+11:00', - '2018-04-01 02:00:00+10:00', - '2018-04-01 03:00:00+10:00', - '2018-04-01 04:00:00+10:00'], freq=None) + result = date_range('2018-04-01 01:00:00', + '2018-04-01 04:00:00', + tz='Australia/Sydney', + periods=3) + expected = DatetimeIndex([Timestamp('2018-04-01 01:00:00+1100', + tz='Australia/Sydney'), + Timestamp('2018-04-01 02:00:00+1000', + tz='Australia/Sydney'), + Timestamp('2018-04-01 04:00:00+1000', + tz='Australia/Sydney')]) + tm.assert_index_equal(result, expected) + + @pytest.mark.parametrize('start,end,result_tz', [ + ['20180101', '20180103', 'US/Eastern'], + [datetime(2018, 1, 1), datetime(2018, 1, 3), 'US/Eastern'], + [Timestamp('20180101'), Timestamp('20180103'), 'US/Eastern'], + [Timestamp('20180101', tz='US/Eastern'), + Timestamp('20180103', tz='US/Eastern'), 'US/Eastern'], + [Timestamp('20180101', tz='US/Eastern'), + Timestamp('20180103', tz='US/Eastern'), None]]) + def test_date_range_linspacing_tz(self, start, end, result_tz): + # GH 20983 + result = date_range(start, end, periods=3, tz=result_tz) + expected = date_range('20180101', periods=3, freq='D', tz='US/Eastern') + tm.assert_index_equal(result, expected) def test_date_range_businesshour(self): idx = DatetimeIndex(['2014-07-04 09:00', '2014-07-04 10:00',