Repository: pydata/xarray

Issue:
"in" operator does not work as expected on DataArray dimensions
As an example I have a DataArray called "my_dataarray" that looks something like this:


```
<xarray.DataArray 'values' (Type: 3)>
array([1, 2, 3])
Coordinates:
  * Type        (Type) object 'Type 1' 'Type 2' 'Type 3'
```

'Type' is a dimension on my DataArray.  Note that 'Type' is also a DataArray that looks like this:

```
OrderedDict([('Type', <xarray.IndexVariable 'Type' (Type: 3)>
array(['Type 1', 'Type 2', 'Type 3'], 
      dtype='object'))])
```

Let's say I run:

```
'Type 1' in my_dataarray.Type
```

The result is False, even though 'Type 1' is in the "Type" dimension.

To get the result I was expecting I need to run:

```
'Type 1' in my_dataarray.Type.values
```

Stepping through the code, the problematic line is here:
https://github.com/pydata/xarray/blob/20ec32430fac63a8976699d9528b5fdc1cd4125d/xarray/core/dataarray.py#L487

The test used for `__contains__(self, key)` on the Type dimension is whether the key is in the `_coords` of Type.  

This is probably the right thing to do when the DataArray is used for storing data, but probably not what we want if the DataArray is being used as a dimension -  it should instead check if 'Type 1' is in the *values* of Type?



Discussion:
pep8speaks: Hello @shoyer! Thanks for submitting the PR.

 - There are no PEP8 issues in the file [`xarray/core/dataarray.py`](https://github.com/shoyer/xarray/blob/84fb32241be1153fb25cc34d0a36efdd230b657f/xarray/core/dataarray.py) !

 - There are no PEP8 issues in the file [`xarray/tests/test_dataarray.py`](https://github.com/shoyer/xarray/blob/84fb32241be1153fb25cc34d0a36efdd230b657f/xarray/tests/test_dataarray.py) !



Patch:
diff --git a/doc/whats-new.rst b/doc/whats-new.rst
index 4497c57e..3a644ddf 100644
--- a/doc/whats-new.rst
+++ b/doc/whats-new.rst
@@ -33,11 +33,14 @@ v0.11.0 (unreleased)
 Breaking changes
 ~~~~~~~~~~~~~~~~
 
-- ``Dataset.T`` has been removed as a shortcut for :py:meth:`Dataset.transpose`.
-  Call :py:meth:`Dataset.transpose` directly instead.
-- Iterating over a ``Dataset`` now includes only data variables, not coordinates.
-  Similarily, calling ``len`` and ``bool`` on a ``Dataset`` now  
-  includes only data variables
+- Finished deprecation cycles:
+  - ``Dataset.T`` has been removed as a shortcut for :py:meth:`Dataset.transpose`.
+    Call :py:meth:`Dataset.transpose` directly instead.
+  - Iterating over a ``Dataset`` now includes only data variables, not coordinates.
+    Similarily, calling ``len`` and ``bool`` on a ``Dataset`` now  
+    includes only data variables.
+  - ``DataArray.__contains__`` (used by Python's ``in`` operator) now checks
+    array data, not coordinates. 
 - Xarray's storage backends now automatically open and close files when
   necessary, rather than requiring opening a file with ``autoclose=True``. A
   global least-recently-used cache is used to store open files; the default
@@ -123,6 +126,10 @@ Bug fixes
   By `Spencer Clark <https://github.com/spencerkclark>`_.
 - Avoid use of Dask's deprecated ``get=`` parameter in tests
   by `Matthew Rocklin <https://github.com/mrocklin/>`_.
+- An ``OverflowError`` is now accurately raised and caught during the
+  encoding process if a reference date is used that is so distant that
+  the dates must be encoded using cftime rather than NumPy (:issue:`2272`).
+  By `Spencer Clark <https://github.com/spencerkclark>`_.
 
 .. _whats-new.0.10.9:
 
diff --git a/xarray/coding/times.py b/xarray/coding/times.py
index dff7e75b..16380976 100644
--- a/xarray/coding/times.py
+++ b/xarray/coding/times.py
@@ -361,7 +361,12 @@ def encode_cf_datetime(dates, units=None, calendar=None):
         delta_units = _netcdf_to_numpy_timeunit(delta)
         time_delta = np.timedelta64(1, delta_units).astype('timedelta64[ns]')
         ref_date = np.datetime64(pd.Timestamp(ref_date))
-        num = (dates - ref_date) / time_delta
+
+        # Wrap the dates in a DatetimeIndex to do the subtraction to ensure
+        # an OverflowError is raised if the ref_date is too far away from
+        # dates to be encoded (GH 2272).
+        num = (pd.DatetimeIndex(dates.ravel()) - ref_date) / time_delta
+        num = num.values.reshape(dates.shape)
 
     except (OutOfBoundsDatetime, OverflowError):
         num = _encode_datetime_with_cftime(dates, units, calendar)
diff --git a/xarray/core/dataarray.py b/xarray/core/dataarray.py
index f131b003..7dc867c9 100644
--- a/xarray/core/dataarray.py
+++ b/xarray/core/dataarray.py
@@ -503,11 +503,7 @@ class DataArray(AbstractArray, DataWithCoords):
                 LevelCoordinatesSource(self)]
 
     def __contains__(self, key):
-        warnings.warn(
-            'xarray.DataArray.__contains__ currently checks membership in '
-            'DataArray.coords, but in xarray v0.11 will change to check '
-            'membership in array values.', FutureWarning, stacklevel=2)
-        return key in self._coords
+        return key in self.data
 
     @property
     def loc(self):


Test patch:
diff --git a/xarray/tests/test_coding_times.py b/xarray/tests/test_coding_times.py
index 10a1a956..8e47bd37 100644
--- a/xarray/tests/test_coding_times.py
+++ b/xarray/tests/test_coding_times.py
@@ -8,7 +8,8 @@ import pandas as pd
 import pytest
 
 from xarray import DataArray, Variable, coding, decode_cf, set_options
-from xarray.coding.times import _import_cftime
+from xarray.coding.times import (_import_cftime, decode_cf_datetime,
+                                 encode_cf_datetime)
 from xarray.coding.variables import SerializationWarning
 from xarray.core.common import contains_cftime_datetimes
 
@@ -763,3 +764,16 @@ def test_contains_cftime_datetimes_non_cftimes(non_cftime_data):
 @pytest.mark.parametrize('non_cftime_data', [DataArray([]), DataArray([1, 2])])
 def test_contains_cftime_datetimes_non_cftimes_dask(non_cftime_data):
     assert not contains_cftime_datetimes(non_cftime_data.chunk())
+
+
+@pytest.mark.skipif(not has_cftime_or_netCDF4, reason='cftime not installed')
+@pytest.mark.parametrize('shape', [(24,), (8, 3), (2, 4, 3)])
+def test_encode_datetime_overflow(shape):
+    # Test for fix to GH 2272
+    dates = pd.date_range('2100', periods=24).values.reshape(shape)
+    units = 'days since 1800-01-01'
+    calendar = 'standard'
+
+    num, _, _ = encode_cf_datetime(dates, units, calendar)
+    roundtrip = decode_cf_datetime(num, units, calendar)
+    np.testing.assert_array_equal(dates, roundtrip)
diff --git a/xarray/tests/test_dataarray.py b/xarray/tests/test_dataarray.py
index e49b6cdf..433a669e 100644
--- a/xarray/tests/test_dataarray.py
+++ b/xarray/tests/test_dataarray.py
@@ -618,9 +618,9 @@ class TestDataArray(object):
         da[dict(x=ind)] = value  # should not raise
 
     def test_contains(self):
-        data_array = DataArray(1, coords={'x': 2})
-        with pytest.warns(FutureWarning):
-            assert 'x' in data_array
+        data_array = DataArray([1, 2])
+        assert 1 in data_array
+        assert 3 not in data_array
 
     def test_attr_sources_multiindex(self):
         # make sure attr-style access for multi-index levels
@@ -2533,6 +2533,7 @@ class TestDataArray(object):
         assert_allclose(actual, expected, rtol=1e-16)
 
     @requires_dask
+    @requires_scipy
     def test_upsample_interpolate_dask(self):
         import dask.array as da