Skip to content

Commit fd2552a

Browse files
spencerkclarkdcherian
authored andcommitted
Enable subtracting a scalar cftime.datetime object from a CFTimeIndex (#2672)
* Enable subtracting a scalar cftime.datetime object from a CFTimeIndex * lint * Test cftime.datetime minus CFTimeIndex as well * Fix cftime minus CFTimeIndex
1 parent e8bf4bf commit fd2552a

File tree

3 files changed

+29
-1
lines changed

3 files changed

+29
-1
lines changed

doc/whats-new.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ Bug fixes
5656
`Spencer Clark <https://github.com/spencerkclark>`_.
5757
- Line plots with the `x` argument set to a non-dimensional coord now plot the correct data for 1D DataArrays.
5858
(:issue:`27251). By `Tom Nicholas <http://github.com/TomNicholas>`_.
59+
- Subtracting a scalar ``cftime.datetime`` object from a
60+
:py:class:`CFTimeIndex` now results in a :py:class:`pandas.TimedeltaIndex`
61+
instead of raising a ``TypeError`` (:issue:`2671`). By `Spencer Clark
62+
<https://github.com/spencerkclark>`_.
5963

6064
.. _whats-new.0.11.3:
6165

xarray/coding/cftimeindex.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,13 +408,17 @@ def __radd__(self, other):
408408
return CFTimeIndex(other + np.array(self))
409409

410410
def __sub__(self, other):
411-
if isinstance(other, CFTimeIndex):
411+
import cftime
412+
if isinstance(other, (CFTimeIndex, cftime.datetime)):
412413
return pd.TimedeltaIndex(np.array(self) - np.array(other))
413414
elif isinstance(other, pd.TimedeltaIndex):
414415
return CFTimeIndex(np.array(self) - other.to_pytimedelta())
415416
else:
416417
return CFTimeIndex(np.array(self) - other)
417418

419+
def __rsub__(self, other):
420+
return pd.TimedeltaIndex(other - np.array(self))
421+
418422
def _add_delta(self, deltas):
419423
# To support TimedeltaIndex + CFTimeIndex with older versions of
420424
# pandas. No longer used as of pandas 0.23.

xarray/tests/test_cftimeindex.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,26 @@ def test_cftimeindex_sub_cftimeindex(calendar):
700700
assert isinstance(result, pd.TimedeltaIndex)
701701

702702

703+
@pytest.mark.skipif(not has_cftime, reason='cftime not installed')
704+
@pytest.mark.parametrize('calendar', _CFTIME_CALENDARS)
705+
def test_cftimeindex_sub_cftime_datetime(calendar):
706+
a = xr.cftime_range('2000', periods=5, calendar=calendar)
707+
result = a - a[0]
708+
expected = pd.TimedeltaIndex([timedelta(days=i) for i in range(5)])
709+
assert result.equals(expected)
710+
assert isinstance(result, pd.TimedeltaIndex)
711+
712+
713+
@pytest.mark.skipif(not has_cftime, reason='cftime not installed')
714+
@pytest.mark.parametrize('calendar', _CFTIME_CALENDARS)
715+
def test_cftime_datetime_sub_cftimeindex(calendar):
716+
a = xr.cftime_range('2000', periods=5, calendar=calendar)
717+
result = a[0] - a
718+
expected = pd.TimedeltaIndex([timedelta(days=-i) for i in range(5)])
719+
assert result.equals(expected)
720+
assert isinstance(result, pd.TimedeltaIndex)
721+
722+
703723
@pytest.mark.skipif(not has_cftime, reason='cftime not installed')
704724
@pytest.mark.parametrize('calendar', _CFTIME_CALENDARS)
705725
def test_cftimeindex_sub_timedeltaindex(calendar):

0 commit comments

Comments
 (0)