diff options
author | Tyler Reddy <tyler.je.reddy@gmail.com> | 2018-08-30 20:48:30 -0700 |
---|---|---|
committer | Tyler Reddy <tyler.je.reddy@gmail.com> | 2018-08-30 20:48:30 -0700 |
commit | bf8c0ce0c085400ba34eceded10f6c9b9de6fae5 (patch) | |
tree | d5e2e54586e072aaed6d14dc03b6a8019c8747d6 /numpy/core | |
parent | febbe2a06a17a877ade8622f0f70f8291dcb4d9a (diff) | |
download | numpy-bf8c0ce0c085400ba34eceded10f6c9b9de6fae5.tar.gz |
BUG: 0D object array to timedelta
* it is now possible to convert
a 0 dimensional object array to
a 0 dimensional NumPy timedelta
array
* the single datetime.timedelta
entry in the 0 D NumPy array
is accessed using __getitem__(())
because integer indexing doesn't
work on 0D NumPy arrays
Diffstat (limited to 'numpy/core')
-rw-r--r-- | numpy/core/src/multiarray/datetime.c | 56 | ||||
-rw-r--r-- | numpy/core/tests/test_datetime.py | 10 |
2 files changed, 54 insertions, 12 deletions
diff --git a/numpy/core/src/multiarray/datetime.c b/numpy/core/src/multiarray/datetime.c index df9b9cec4..7f837901c 100644 --- a/numpy/core/src/multiarray/datetime.c +++ b/numpy/core/src/multiarray/datetime.c @@ -3747,6 +3747,27 @@ recursive_find_object_datetime64_type(PyObject *obj, } /* + * handler function for PyDelta values + * which may also be in a 0 dimensional + * NumPy array + */ +static int +delta_checker(PyArray_DatetimeMetaData *meta) +{ + PyArray_DatetimeMetaData tmp_meta; + + tmp_meta.base = NPY_FR_us; + tmp_meta.num = 1; + + /* Combine it with 'meta' */ + if (compute_datetime_metadata_greatest_common_divisor( + meta, &tmp_meta, meta, 0, 0) < 0) { + return -1; + } + return 0; +} + +/* * Recursively determines the metadata for an NPY_TIMEDELTA dtype. * * Returns 0 on success, -1 on failure. @@ -3783,6 +3804,28 @@ recursive_find_object_timedelta64_type(PyObject *obj, else if (arr_dtype->type_num != NPY_OBJECT) { return 0; } + else { + if (PyArray_NDIM(arr) == 0) { + /* + * special handling of 0 dimensional NumPy object + * arrays, which may be indexed to retrieve their + * single object using [()], but not by using + * __getitem__(integer) approaches + */ + PyObject *item, *meth, *args; + + meth = PyObject_GetAttrString(obj, "__getitem__"); + args = Py_BuildValue("(())"); + item = PyObject_CallObject(meth, args); + /* + * NOTE: may need other type checks here in the future + * for expanded 0 D datetime array conversions? + */ + if (PyDelta_Check(item)) { + return delta_checker(meta); + } + } + } } /* Datetime scalar -> use its metadata */ else if (PyArray_IsScalar(obj, Timedelta)) { @@ -3803,18 +3846,7 @@ recursive_find_object_timedelta64_type(PyObject *obj, } /* Python timedelta object -> 'us' */ else if (PyDelta_Check(obj)) { - PyArray_DatetimeMetaData tmp_meta; - - tmp_meta.base = NPY_FR_us; - tmp_meta.num = 1; - - /* Combine it with 'meta' */ - if (compute_datetime_metadata_greatest_common_divisor(meta, - &tmp_meta, meta, 0, 0) < 0) { - return -1; - } - - return 0; + return delta_checker(meta); } /* Now check if what we have left is a sequence for recursion */ diff --git a/numpy/core/tests/test_datetime.py b/numpy/core/tests/test_datetime.py index 8e058d5fb..a5e1f73ce 100644 --- a/numpy/core/tests/test_datetime.py +++ b/numpy/core/tests/test_datetime.py @@ -355,6 +355,16 @@ class TestDateTime(object): actual = np.array(inputs, dtype='timedelta64[D]') assert_equal(expected, actual) + def test_timedelta_0_dim_object_array_conversion(self): + # Regression test for gh-11151 + test = np.array(datetime.timedelta(seconds=20)) + actual = test.astype(np.timedelta64) + # expected value from the array constructor workaround + # described in above issue + expected = np.array(datetime.timedelta(seconds=20), + np.timedelta64) + assert_equal(actual, expected) + def test_timedelta_scalar_construction_units(self): # String construction detecting units assert_equal(np.datetime64('2010').dtype, |