Description
TL;DR: can we assume that np.float128 exists (and is actually 128 bits)? If so then this has an easy solution. Otherwise, it's easy-but-tedious. update Turns out the np.float128 solution doesn't as easily as I expected.
start = pd.Timestamp('1700-01-01')
end = pd.Timestamp('2250-12-31')
dti = pd.date_range(start, end, freq='D')
# alternative construction that _should_ work
dti2 = pd.date_range(start, periods=len(dti), freq='D') # raises OutOfBoundsDatetime
dti3 = pd.date_range(end=end, periods=len(dti), freq='D') # raises OutOfBoundsDatetime
It's actually worse than that, because it is raising the wrong OutOfBoundsDatetime. What is happening here is that in arrays.datetimes._generate_range_overflow_safe we are doing:
try:
other_end = checked_add_with_arr(np.int64(endpoint),
np.int64(periods) * stride)
except OverflowError:
raise tslib.OutOfBoundsDatetime('Cannot generate range with '
In these cases, np.int64(periods) * stride
is wrapping around.
The good news is that this is fairly easy to fix by casting to np.uint64
instead of np.int64
. The bad news is that when we call checked_add_with_arr
, if the arguments have mismatched dtypes, then it gives back a float64, and we can get an incorrect result when casting back to int64.
Obvious next step: OK, so let's pass args with matching dtypes. if endpoint
is positive we can cast it to uint64 and we're done. Otherwise [break down into 5 cases..., straightforward but tedious]
The alternative is to just cast to np.float128, do both the multiplication and addition there, then check for overflows before casting back to int64. But IIRC some (windows) platforms don't have a "real" float128. Is that a sufficiently ancient case that it can be ignored?