Repository: pydata/xarray

Issue:
interp over time coordinate
Before I start, I'm very excited about the interp addition in 0.10.7. Great addition and thanks to @fujiisoup and @shoyer.

I see there was a bit of a discussion in the interp pull request,  #2104, about interpolating over times and that it was suggested to wait for use cases. I can think of an immediate use case in my line of work.
I frequently use regular gridded geophysical data (time, lat, lon), not unlike the sample tutorial air_temperature data,  and the data must be interpolated to line up with corresponding satellite measurements that are irregularly spaced in lat, lon and time.

Being able to interpolate in one quick step would be fantastic. For example:

```python
ds = xr.tutorial.load_dataset('air_temperature')
ds.interp(lat=60.5, lon=211, time='2013-01-01T03:14:37')
```
#### Problem description
Currently issues `TypeError: cannot perform reduce with flexible type`.

#### Desired Output
```
<xarray.Dataset>
Dimensions:  ()
Coordinates:
    lat      float64 60.5
    lon      int64 211
    time    datetime64[ns] 2013-01-01T03:14:37
Data variables:
    air      float64 273.5
```

Discussion:
fujiisoup: Thanks, @dcherian .

It looks already great, but can you add a bit more test cases to keep it working with the future modification?
It would be nicer if we can check
+ If `xnew` is a single datetime unicode such as '2014-05-07`
+ If `xnew` is pd.datetime

I think they will be passing though.
fujiisoup: Can you merge master? It will solve some failures in CI.
I also noticed tests in Python=2.7 are failing.

Patch:
diff --git a/doc/interpolation.rst b/doc/interpolation.rst
index 7b483ed0..e5230e95 100644
--- a/doc/interpolation.rst
+++ b/doc/interpolation.rst
@@ -48,15 +48,13 @@ array-like, which gives the interpolated result as an array.
     # interpolation
     da.interp(time=[2.5, 3.5])
 
-
-To interpolate data with a :py:func:`numpy.datetime64` coordinate you have to
-wrap it explicitly in a :py:func:`numpy.datetime64` object.
+To interpolate data with a :py:func:`numpy.datetime64` coordinate you can pass a string.
 
 .. ipython:: python
 
     da_dt64 = xr.DataArray([1, 3],
                            [('time', pd.date_range('1/1/2000', '1/3/2000', periods=2))])
-    da_dt64.interp(time=np.datetime64('2000-01-02'))
+    da_dt64.interp(time='2000-01-02')
 
 The interpolated data can be merged into the original :py:class:`~xarray.DataArray`
 by specifing the time periods required.
diff --git a/doc/whats-new.rst b/doc/whats-new.rst
index af485015..02ab7780 100644
--- a/doc/whats-new.rst
+++ b/doc/whats-new.rst
@@ -41,6 +41,10 @@ Enhancements
   (:issue:`1186`)
   By `Seth P <https://github.com/seth-p>`_.
 
+- When interpolating over a ``datetime64`` axis, you can now provide a datetime string instead of a ``datetime64`` object. E.g. ``da.interp(time='1991-02-01')``
+  (:issue:`2284`)
+  By `Deepak Cherian <https://github.com/dcherian>`_.
+
 
 Bug fixes
 ~~~~~~~~~
diff --git a/xarray/core/dataset.py b/xarray/core/dataset.py
index 8e039572..4b52178a 100644
--- a/xarray/core/dataset.py
+++ b/xarray/core/dataset.py
@@ -1308,6 +1308,8 @@ class Dataset(Mapping, ImplementsDatasetReduce, DataWithCoords,
         """ Here we make sure
         + indexer has a valid keys
         + indexer is in a valid data type
+        * string indexers are cast to datetime64
+          if associated index is DatetimeIndex
         """
         from .dataarray import DataArray
 
@@ -1328,6 +1330,12 @@ class Dataset(Mapping, ImplementsDatasetReduce, DataWithCoords,
                 raise TypeError('cannot use a Dataset as an indexer')
             else:
                 v = np.asarray(v)
+
+                if ((v.dtype.kind == 'U' or v.dtype.kind == 'S')
+                    and isinstance(self.coords[k].to_index(),
+                                 pd.DatetimeIndex)):
+                    v = v.astype('datetime64[ns]')
+
                 if v.ndim == 0:
                     v = as_variable(v)
                 elif v.ndim == 1:


Test patch:
diff --git a/xarray/tests/test_interp.py b/xarray/tests/test_interp.py
index 69a4644b..4a8f4e6e 100644
--- a/xarray/tests/test_interp.py
+++ b/xarray/tests/test_interp.py
@@ -462,19 +462,31 @@ def test_interp_like():
 
 
 @requires_scipy
-def test_datetime():
-    da = xr.DataArray(np.random.randn(24), dims='time',
+@pytest.mark.parametrize('x_new, expected', [
+    (pd.date_range('2000-01-02', periods=3), [1, 2, 3]),
+    (np.array([np.datetime64('2000-01-01T12:00'),
+               np.datetime64('2000-01-02T12:00')]), [0.5, 1.5]),
+    (['2000-01-01T12:00', '2000-01-02T12:00'], [0.5, 1.5]),
+    (['2000-01-01T12:00'], 0.5),
+    pytest.param('2000-01-01T12:00', 0.5, marks=pytest.mark.xfail)
+])
+def test_datetime(x_new, expected):
+    da = xr.DataArray(np.arange(24), dims='time',
                       coords={'time': pd.date_range('2000-01-01', periods=24)})
 
-    x_new = pd.date_range('2000-01-02', periods=3)
     actual = da.interp(time=x_new)
-    expected = da.isel(time=[1, 2, 3])
-    assert_allclose(actual, expected)
+    expected_da = xr.DataArray(np.atleast_1d(expected), dims=['time'],
+                               coords={'time': (np.atleast_1d(x_new)
+                                                .astype('datetime64[ns]'))})
 
-    x_new = np.array([np.datetime64('2000-01-01T12:00'),
-                      np.datetime64('2000-01-02T12:00')])
-    actual = da.interp(time=x_new)
-    assert_allclose(actual.isel(time=0).drop('time'),
-                    0.5 * (da.isel(time=0) + da.isel(time=1)))
-    assert_allclose(actual.isel(time=1).drop('time'),
-                    0.5 * (da.isel(time=1) + da.isel(time=2)))
+    assert_allclose(actual, expected_da)
+
+
+@requires_scipy
+def test_datetime_single_string():
+    da = xr.DataArray(np.arange(24), dims='time',
+                      coords={'time': pd.date_range('2000-01-01', periods=24)})
+    actual = da.interp(time='2000-01-01T12:00')
+    expected = xr.DataArray(0.5)
+
+    assert_allclose(actual.drop('time'), expected)