Skip to content

Commit 977b384

Browse files
gfyoungjreback
authored andcommitted
BUG: Check for overflow in TimedeltaIndex addition.
Title is self-explanatory. Closes #14068. Author: gfyoung <[email protected]> Closes #14237 from gfyoung/add-overflow and squashes the following commits: 77effde [gfyoung] BUG: Check for overflow in TimedeltaIndex addition.
1 parent b81d444 commit 977b384

File tree

5 files changed

+56
-1
lines changed

5 files changed

+56
-1
lines changed

doc/source/whatsnew/v0.19.0.txt

+2
Original file line numberDiff line numberDiff line change
@@ -1425,6 +1425,8 @@ Bug Fixes
14251425
- Bug in selection from a ``HDFStore`` with a fixed format and ``start`` and/or ``stop`` specified will now return the selected range (:issue:`8287`)
14261426
- Bug in ``Categorical.from_codes()`` where an unhelpful error was raised when an invalid ``ordered`` parameter was passed in (:issue:`14058`)
14271427
- Bug in ``Series`` construction from a tuple of integers on windows not returning default dtype (int64) (:issue:`13646`)
1428+
- Bug in ``TimedeltaIndex`` addition with a Datetime-like object where addition overflow was not being caught (:issue:`14068`)
1429+
14281430
- Bug in ``.groupby(..).resample(..)`` when the same object is called multiple times (:issue:`13174`)
14291431
- Bug in ``.to_records()`` when index name is a unicode string (:issue:`13172`)
14301432

pandas/core/nanops.py

+26
Original file line numberDiff line numberDiff line change
@@ -809,3 +809,29 @@ def unique1d(values):
809809
table = _hash.PyObjectHashTable(len(values))
810810
uniques = table.unique(_ensure_object(values))
811811
return uniques
812+
813+
814+
def _checked_add_with_arr(arr, b):
815+
"""
816+
Performs the addition of an int64 array and an int64 integer (or array)
817+
but checks that they do not result in overflow first.
818+
819+
Parameters
820+
----------
821+
arr : array addend.
822+
b : array or scalar addend.
823+
824+
Returns
825+
-------
826+
sum : An array for elements x + b for each element x in arr if b is
827+
a scalar or an array for elements x + y for each element pair
828+
(x, y) in (arr, b).
829+
830+
Raises
831+
------
832+
OverflowError if any x + y exceeds the maximum int64 value.
833+
"""
834+
if (np.iinfo(np.int64).max - b < arr).any():
835+
raise OverflowError("Python int too large to "
836+
"convert to C long")
837+
return arr + b

pandas/tests/test_nanops.py

+15
Original file line numberDiff line numberDiff line change
@@ -1002,6 +1002,21 @@ def prng(self):
10021002
return np.random.RandomState(1234)
10031003

10041004

1005+
def test_int64_add_overflow():
1006+
# see gh-14068
1007+
msg = "too (big|large) to convert"
1008+
m = np.iinfo(np.int64).max
1009+
1010+
with tm.assertRaisesRegexp(OverflowError, msg):
1011+
nanops._checked_add_with_arr(np.array([m, m]), m)
1012+
with tm.assertRaisesRegexp(OverflowError, msg):
1013+
nanops._checked_add_with_arr(np.array([m, m]), np.array([m, m]))
1014+
with tm.assertRaisesRegexp(OverflowError, msg):
1015+
with tm.assert_produces_warning(RuntimeWarning):
1016+
nanops._checked_add_with_arr(np.array([m, m]),
1017+
np.array([np.nan, m]))
1018+
1019+
10051020
if __name__ == '__main__':
10061021
import nose
10071022
nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure', '-s'

pandas/tseries/tdi.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from pandas.compat import u
2222
from pandas.tseries.frequencies import to_offset
2323
from pandas.core.base import _shared_docs
24+
from pandas.core.nanops import _checked_add_with_arr
2425
from pandas.indexes.base import _index_shared_docs
2526
import pandas.core.common as com
2627
import pandas.types.concat as _concat
@@ -343,7 +344,7 @@ def _add_datelike(self, other):
343344
else:
344345
other = Timestamp(other)
345346
i8 = self.asi8
346-
result = i8 + other.value
347+
result = _checked_add_with_arr(i8, other.value)
347348
result = self._maybe_mask_results(result, fill_value=tslib.iNaT)
348349
return DatetimeIndex(result, name=self.name, copy=False)
349350

pandas/tseries/tests/test_timedeltas.py

+11
Original file line numberDiff line numberDiff line change
@@ -1950,6 +1950,17 @@ def test_tdi_ops_attributes(self):
19501950
tm.assert_index_equal(result, exp)
19511951
self.assertEqual(result.freq, None)
19521952

1953+
def test_add_overflow(self):
1954+
# see gh-14068
1955+
msg = "too (big|large) to convert"
1956+
with tm.assertRaisesRegexp(OverflowError, msg):
1957+
to_timedelta(106580, 'D') + Timestamp('2000')
1958+
with tm.assertRaisesRegexp(OverflowError, msg):
1959+
Timestamp('2000') + to_timedelta(106580, 'D')
1960+
with tm.assertRaisesRegexp(OverflowError, msg):
1961+
to_timedelta([106580], 'D') + Timestamp('2000')
1962+
with tm.assertRaisesRegexp(OverflowError, msg):
1963+
Timestamp('2000') + to_timedelta([106580], 'D')
19531964

19541965
if __name__ == '__main__':
19551966
nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'],

0 commit comments

Comments
 (0)