summaryrefslogtreecommitdiff
path: root/numpy/core
diff options
context:
space:
mode:
authorTyler Reddy <tyler.je.reddy@gmail.com>2018-08-30 20:48:30 -0700
committerTyler Reddy <tyler.je.reddy@gmail.com>2018-08-30 20:48:30 -0700
commitbf8c0ce0c085400ba34eceded10f6c9b9de6fae5 (patch)
treed5e2e54586e072aaed6d14dc03b6a8019c8747d6 /numpy/core
parentfebbe2a06a17a877ade8622f0f70f8291dcb4d9a (diff)
downloadnumpy-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.c56
-rw-r--r--numpy/core/tests/test_datetime.py10
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,