Skip to content

Commit 56510e3

Browse files
author
Gabriel Reid
committed
BUG: date_range issue with sub-second granularity
Fixes pandas-dev#24110, by avoid floating-point rounding issues with sub-second granularity timestamps when creating a date range.
1 parent b78aa8d commit 56510e3

File tree

3 files changed

+15
-1
lines changed

3 files changed

+15
-1
lines changed

doc/source/whatsnew/v0.24.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -1305,6 +1305,7 @@ Datetimelike
13051305
- Bug in :class:`DatetimeIndex` where calling ``np.array(dtindex, dtype=object)`` would incorrectly return an array of ``long`` objects (:issue:`23524`)
13061306
- Bug in :class:`Index` where passing a timezone-aware :class:`DatetimeIndex` and `dtype=object` would incorrectly raise a ``ValueError`` (:issue:`23524`)
13071307
- Bug in :class:`Index` where calling ``np.array(dtindex, dtype=object)`` on a timezone-naive :class:`DatetimeIndex` would return an array of ``datetime`` objects instead of :class:`Timestamp` objects, potentially losing nanosecond portions of the timestamps (:issue:`23524`)
1308+
- Bug in :func:`date_range` where using dates with sub-second granularity could return incorrect values or the wrong number of values in the index (:issue:`24110`)
13081309

13091310
Timedelta
13101311
^^^^^^^^^

pandas/core/arrays/datetimes.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,12 @@ def _generate_range(cls, start, end, periods, freq, tz=None,
307307
end = end.tz_localize(tz).asm8
308308
else:
309309
# Create a linearly spaced date_range in local time
310-
arr = np.linspace(start.value, end.value, periods)
310+
# Nanosecond-granularity timestamps aren't always correctly
311+
# representable with doubles, so we limit the range that we
312+
# pass to np.linspace as much as possible
313+
arr = np.linspace(
314+
0, end.value - start.value,
315+
periods, dtype='int64') + start.value
311316
index = cls._simple_new(
312317
arr.astype('M8[ns]', copy=False), freq=None, tz=tz
313318
)

pandas/tests/indexes/datetimes/test_date_range.py

+8
Original file line numberDiff line numberDiff line change
@@ -769,3 +769,11 @@ def test_all_custom_freq(self, freq):
769769
msg = 'invalid custom frequency string: {freq}'
770770
with pytest.raises(ValueError, match=msg.format(freq=bad_freq)):
771771
bdate_range(START, END, freq=bad_freq)
772+
773+
def test_range_with_millisecond_granularity(self):
774+
# https://github.com/pandas-dev/pandas/issues/24110
775+
start = '2018-01-01T00:00:00.010Z'
776+
end = '2018-01-03T00:00:00.010Z'
777+
result = pd.date_range(start=start, end=end, periods=2, closed='left')
778+
expected = DatetimeIndex([start])
779+
tm.assert_index_equal(result, expected)

0 commit comments

Comments
 (0)