Repository: numpy/numpy
Pull request: DOC: Explaining why datetime64 doesn't work for allclose + isclose
<!-- Please be sure you are following the instructions in the dev guidelines
http://www.numpy.org/devdocs/dev/development_workflow.html
-->

<!-- We'd appreciate it if your commit message is properly formatted
http://www.numpy.org/devdocs/dev/development_workflow.html#writing-the-commit-message
-->

Providing documentation to detail why datetime64 doesn't work with functions `allclose` and `isclose` .
See #16065 for details. 

Fixes #16065

Problem statement:
Passing datetime64 to `isclose` or `allclose` raises TypeError
When passing datetime64 arrays to `isclose` or `allclose`, the exception `TypeError: invalid type promotion` is raised.  The issue stems from `multiarray.result_type` not understanding or not implementing `np.datetime64`, perhaps?

### Reproducing code example:
```python
import numpy as np

x = np.array([['1970-01-01T00:00:00.000000000'],
              ['1970-01-01T00:00:01.000000000'],
              ['1970-01-01T00:00:02.000000000']], dtype='datetime64[ns]')

y = np.array([['1970-01-01T00:00:00.000000000'],
              ['1970-01-01T00:00:01.000000000'],
              ['1970-01-01T00:00:02.300000000']], dtype='datetime64[ns]')

np.isclose(x, y)
# raises TypeError: invalid type promotion

np.allclose(x, y)
# raises TypeError: invalid type promotion

np.core.multiarray.result_type(x, 1.)
# raises TypeError: invalid type promotion
```

### Error message:
These errors were created in interactive mode.

Traceback from `np.isclose(x, y)`:
```
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<__array_function__ internals>", line 6, in isclose
  File "C:\Users\james\.conda\envs\test\lib\site-packages\numpy\core\numeric.py", line 2254, in isclose
    dt = multiarray.result_type(y, 1.)
  File "<__array_function__ internals>", line 6, in result_type
TypeError: invalid type promotion
```

Traceback from `np.isclose(x, y)`:
```
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<__array_function__ internals>", line 6, in allclose
  File "C:\Users\james\.conda\envs\test\lib\site-packages\numpy\core\numeric.py", line 2159, in allclose
    res = all(isclose(a, b, rtol=rtol, atol=atol, equal_nan=equal_nan))
  File "<__array_function__ internals>", line 6, in isclose
  File "C:\Users\james\.conda\envs\test\lib\site-packages\numpy\core\numeric.py", line 2254, in isclose
    dt = multiarray.result_type(y, 1.)
  File "<__array_function__ internals>", line 6, in result_type
TypeError: invalid type promotion
```

Traceback from `np.core.multiarray.result_type(x, 1.)`:
```
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<__array_function__ internals>", line 6, in result_type
TypeError: invalid type promotion
```

### Numpy/Python version information:

1.18.1 3.7.7 (default, Apr 15 2020, 05:09:04) [MSC v.1916 64 bit (AMD64)]

Hints from issue discussion:
I think the closeness of `datetime64` doesn't fit the semantic of `isclose`, which is basically `absolute(a - b) <= (atol + rtol * absolute(b))`, particularly because of the relative tolerance: there is no multiplication of `datetime64` with scalar. If we used Unix time, the closeness would depend on the choice of the epoch, which is absurd: 1970-01-02 would be closer to 1970-01-03 than to 1970-01-01!
Perhaps the exception or documentation could be improved here.

Commit message: DOC:Explaining why datetime64 doesn't work for allclose + isclose

Patch to review:
diff --git a/numpy/core/numeric.py b/numpy/core/numeric.py
index e77161f59dd7..8f95e04e9f27 100644
--- a/numpy/core/numeric.py
+++ b/numpy/core/numeric.py
@@ -2173,6 +2173,8 @@ def allclose(a, b, rtol=1.e-5, atol=1.e-8, equal_nan=False):
     ``allclose(a, b)`` to evaluate to True.  The same is true for
     `equal` but not `array_equal`.
 
+    ``allclose`` is currently not defined for non-numeric data types.
+
     Examples
     --------
     >>> np.allclose([1e10,1e-7], [1.00001e10,1e-8])
@@ -2252,6 +2254,8 @@ def isclose(a, b, rtol=1.e-5, atol=1.e-8, equal_nan=False):
     `atol` should be carefully selected for the use case at hand. A zero value
     for `atol` will result in `False` if either `a` or `b` is zero.
 
+    ``isclose`` is currently not defined for non-numeric data types.
+
     Examples
     --------
     >>> np.isclose([1e10,1e-7], [1.00001e10,1e-8])


Code review comments:
diff_hunk: @@ -2252,6 +2254,8 @@ def isclose(a, b, rtol=1.e-5, atol=1.e-8, equal_nan=False):
     `atol` should be carefully selected for the use case at hand. A zero value
     for `atol` will result in `False` if either `a` or `b` is zero.
 
+    ``isclose`` is currently not defined for non-numeric data types.
path: numpy/core/numeric.py
text: @user1:
Same comment as above:
```suggestion
    `isclose` is not defined for non-numeric data types.
```

diff_hunk: @@ -2173,6 +2173,8 @@ def allclose(a, b, rtol=1.e-5, atol=1.e-8, equal_nan=False):
     ``allclose(a, b)`` to evaluate to True.  The same is true for
     `equal` but not `array_equal`.
 
+    ``allclose`` is currently not defined for non-numeric data types.
path: numpy/core/numeric.py
text: @user1:
Drop the word "currently".  Even if we are planning to define this function for non-numeric types some time in the future, there is no need to hint at that in the current docstring.  Also, since it is just a reference to the name and not actual code, use single backticks around `allclose`.
```suggestion
    `allclose` is not defined for non-numeric data types.
```