diff --git a/doc/source/whatsnew/v0.15.2.txt b/doc/source/whatsnew/v0.15.2.txt index ee30e0bdadc5d..97cbecd4bb0e7 100644 --- a/doc/source/whatsnew/v0.15.2.txt +++ b/doc/source/whatsnew/v0.15.2.txt @@ -61,3 +61,4 @@ Bug Fixes - ``io.data.Options`` now raises ``RemoteDataError`` when no expiry dates are available from Yahoo and when it receives no data from Yahoo (:issue:`8761`), (:issue:`8783`). - Bug in slicing a multi-index with an empty list and at least one boolean indexer (:issue:`8781`) - ``io.data.Options`` now raises ``RemoteDataError`` when no expiry dates are available from Yahoo (:issue:`8761`). +- ``Timedelta`` kwargs may now be numpy ints and floats (:issue:`8757`). diff --git a/pandas/tseries/tests/test_timedeltas.py b/pandas/tseries/tests/test_timedeltas.py index 11bf22a055b8f..c8dd5573370d9 100644 --- a/pandas/tseries/tests/test_timedeltas.py +++ b/pandas/tseries/tests/test_timedeltas.py @@ -38,12 +38,24 @@ def test_construction(self): self.assertEqual(Timedelta(10.0,unit='d').value, expected) self.assertEqual(Timedelta('10 days').value, expected) self.assertEqual(Timedelta(days=10).value, expected) + self.assertEqual(Timedelta(days=10.0).value, expected) expected += np.timedelta64(10,'s').astype('m8[ns]').view('i8') self.assertEqual(Timedelta('10 days 00:00:10').value, expected) self.assertEqual(Timedelta(days=10,seconds=10).value, expected) self.assertEqual(Timedelta(days=10,milliseconds=10*1000).value, expected) self.assertEqual(Timedelta(days=10,microseconds=10*1000*1000).value, expected) + + # test construction with np dtypes + # GH 8757 + timedelta_kwargs = {'days':'D', 'seconds':'s', 'microseconds':'us', + 'milliseconds':'ms', 'minutes':'m', 'hours':'h', 'weeks':'W'} + npdtypes = [np.int64, np.int32, np.int16, + np.float64, np.float32, np.float16] + for npdtype in npdtypes: + for pykwarg, npkwarg in timedelta_kwargs.items(): + expected = np.timedelta64(1, npkwarg).astype('m8[ns]').view('i8') + self.assertEqual(Timedelta(**{pykwarg:npdtype(1)}).value, expected) # rounding cases self.assertEqual(Timedelta(82739999850000).value, 82739999850000) diff --git a/pandas/tslib.pyx b/pandas/tslib.pyx index ffe94a94b15b5..30c18e2d5d594 100644 --- a/pandas/tslib.pyx +++ b/pandas/tslib.pyx @@ -37,7 +37,7 @@ from datetime import time as datetime_time from dateutil.tz import (tzoffset, tzlocal as _dateutil_tzlocal, tzfile as _dateutil_tzfile, tzutc as _dateutil_tzutc, gettz as _dateutil_gettz) from pytz.tzinfo import BaseTzInfo as _pytz_BaseTzInfo -from pandas.compat import parse_date, string_types, PY3 +from pandas.compat import parse_date, string_types, PY3, iteritems from sys import version_info import operator @@ -1619,6 +1619,7 @@ class Timedelta(_Timedelta): Denote the unit of the input, if input is an integer. Default 'ns'. days, seconds, microseconds, milliseconds, minutes, hours, weeks : numeric, optional Values for construction in compat with datetime.timedelta. + np ints and floats will be coereced to python ints and floats. Notes ----- @@ -1632,9 +1633,19 @@ class Timedelta(_Timedelta): if value is None: if not len(kwargs): raise ValueError("cannot construct a TimeDelta without a value/unit or descriptive keywords (days,seconds....)") + + def _to_py_int_float(v): + if is_integer_object(v): + return int(v) + elif is_float_object(v): + return float(v) + raise TypeError("Invalid type {0}. Must be int or float.".format(type(v))) + + kwargs = dict([ (k, _to_py_int_float(v)) for k, v in iteritems(kwargs) ]) + try: value = timedelta(**kwargs) - except (TypeError): + except TypeError as e: raise ValueError("cannot construct a TimeDelta from the passed arguments, allowed keywords are " "[days, seconds, microseconds, milliseconds, minutes, hours, weeks]")