diff options
| author | Charles Harris <charlesr.harris@gmail.com> | 2016-01-14 10:22:51 -0700 |
|---|---|---|
| committer | Charles Harris <charlesr.harris@gmail.com> | 2016-01-14 10:22:51 -0700 |
| commit | 8fa6e3bef26a6d4a2c92f2824129aa4409be2590 (patch) | |
| tree | 754b8bdc2fb5ebd27847edc84458127322bb5e78 /numpy | |
| parent | 51d2ecdc7a0aad61e250f9c67a040b0ecae086c3 (diff) | |
| parent | 33adec24a1403df5c47afe235ac1869a8f489489 (diff) | |
| download | numpy-8fa6e3bef26a6d4a2c92f2824129aa4409be2590.tar.gz | |
Merge pull request #6465 from shoyer/datetime64-NaT-casting
BUG: fix casting rules for generic datetime64/timedelta64 dtypes
Diffstat (limited to 'numpy')
| -rw-r--r-- | numpy/core/src/multiarray/datetime.c | 22 | ||||
| -rw-r--r-- | numpy/core/tests/test_datetime.py | 21 |
2 files changed, 35 insertions, 8 deletions
diff --git a/numpy/core/src/multiarray/datetime.c b/numpy/core/src/multiarray/datetime.c index 9e4e00e9c..264178d30 100644 --- a/numpy/core/src/multiarray/datetime.c +++ b/numpy/core/src/multiarray/datetime.c @@ -1232,12 +1232,18 @@ datetime_metadata_divides( { npy_uint64 num1, num2; - /* Generic units divide into anything */ - if (divisor->base == NPY_FR_GENERIC) { + /* + * Any unit can always divide into generic units. In other words, we + * should be able to convert generic units into any more specific unit. + */ + if (dividend->base == NPY_FR_GENERIC) { return 1; } - /* Non-generic units never divide into generic units */ - else if (dividend->base == NPY_FR_GENERIC) { + /* + * However, generic units cannot always divide into more specific units. + * We cannot safely convert datetimes with units back into generic units. + */ + else if (divisor->base == NPY_FR_GENERIC) { return 0; } @@ -1330,7 +1336,7 @@ can_cast_datetime64_units(NPY_DATETIMEUNIT src_unit, */ case NPY_SAME_KIND_CASTING: if (src_unit == NPY_FR_GENERIC || dst_unit == NPY_FR_GENERIC) { - return src_unit == dst_unit; + return src_unit == NPY_FR_GENERIC; } else { return (src_unit <= NPY_FR_D && dst_unit <= NPY_FR_D) || @@ -1344,7 +1350,7 @@ can_cast_datetime64_units(NPY_DATETIMEUNIT src_unit, */ case NPY_SAFE_CASTING: if (src_unit == NPY_FR_GENERIC || dst_unit == NPY_FR_GENERIC) { - return src_unit == dst_unit; + return src_unit == NPY_FR_GENERIC; } else { return (src_unit <= dst_unit) && @@ -1380,7 +1386,7 @@ can_cast_timedelta64_units(NPY_DATETIMEUNIT src_unit, */ case NPY_SAME_KIND_CASTING: if (src_unit == NPY_FR_GENERIC || dst_unit == NPY_FR_GENERIC) { - return src_unit == dst_unit; + return src_unit == NPY_FR_GENERIC; } else { return (src_unit <= NPY_FR_M && dst_unit <= NPY_FR_M) || @@ -1394,7 +1400,7 @@ can_cast_timedelta64_units(NPY_DATETIMEUNIT src_unit, */ case NPY_SAFE_CASTING: if (src_unit == NPY_FR_GENERIC || dst_unit == NPY_FR_GENERIC) { - return src_unit == dst_unit; + return src_unit == NPY_FR_GENERIC; } else { return (src_unit <= dst_unit) && diff --git a/numpy/core/tests/test_datetime.py b/numpy/core/tests/test_datetime.py index 8a8eafee8..360463d38 100644 --- a/numpy/core/tests/test_datetime.py +++ b/numpy/core/tests/test_datetime.py @@ -114,6 +114,27 @@ class TestDateTime(TestCase): # Can cast safely if the integer multiplier does divide assert_(np.can_cast('M8[6h]', 'M8[3h]', casting='safe')) + # We can always cast types with generic units (corresponding to NaT) to + # more specific types + assert_(np.can_cast('m8', 'm8[h]', casting='same_kind')) + assert_(np.can_cast('m8', 'm8[h]', casting='safe')) + assert_(np.can_cast('M8', 'M8[h]', casting='same_kind')) + assert_(np.can_cast('M8', 'M8[h]', casting='safe')) + # but not the other way around + assert_(not np.can_cast('m8[h]', 'm8', casting='same_kind')) + assert_(not np.can_cast('m8[h]', 'm8', casting='safe')) + assert_(not np.can_cast('M8[h]', 'M8', casting='same_kind')) + assert_(not np.can_cast('M8[h]', 'M8', casting='safe')) + + def test_compare_generic_nat(self): + # regression tests for GH6452 + assert_equal(np.datetime64('NaT'), + np.datetime64('2000') + np.timedelta64('NaT')) + # nb. we may want to make NaT != NaT true in the future; this test + # verifies the existing behavior (and that it should not warn) + assert_(np.datetime64('NaT') == np.datetime64('NaT', 'us')) + assert_(np.datetime64('NaT', 'us') == np.datetime64('NaT')) + def test_datetime_scalar_construction(self): # Construct with different units assert_equal(np.datetime64('1950-03-12', 'D'), |
