diff --git a/doc/whats-new.rst b/doc/whats-new.rst index b585c69..db61c3c 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -7,6 +7,8 @@ What's New v0.7.0 (unreleased) ------------------- +- ``interpolate``: Added support for timedelta coordinates; + fixed support for datetime coordinates other than ``M8[ns]`` in xarray 2025.1.2. .. _whats-new.0.6.0: diff --git a/pyproject.toml b/pyproject.toml index 2b7b46f..2375a75 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -70,12 +70,13 @@ filterwarnings = [ "error", # FIXME these need to be fixed in xarray "ignore:__array_wrap__ must accept context and return:DeprecationWarning", - "ignore:__array__ implementation doesn't accept a copy keyword, so passing copy=False failed:DeprecationWarning", # FIXME these need to be looked at 'ignore:.*will no longer be implicitly promoted:FutureWarning', 'ignore:.*updating coordinate .* with a PandasMultiIndex would leave the multi-index level coordinates .* in an inconsistent state:FutureWarning', - # xarray vs. pandas upstream + # These have been fixed; still needed for Python 3.9 CI + "ignore:__array__ implementation doesn't accept a copy keyword, so passing copy=False failed:DeprecationWarning", 'ignore:Converting non-nanosecond precision datetime:UserWarning', + 'ignore:Converting non-nanosecond precision timedelta:UserWarning', ] [tool.coverage.report] diff --git a/xarray_extras/interpolate.py b/xarray_extras/interpolate.py index 5b89e4c..0e7a2bd 100644 --- a/xarray_extras/interpolate.py +++ b/xarray_extras/interpolate.py @@ -68,10 +68,12 @@ def splrep(a: xarray.DataArray, dim: Hashable, k: int = 3) -> xarray.Dataset: a = a.transpose(dim, *[d for d in a.dims if d != dim]) x = a.coords[dim].values - if x.dtype.kind == "M": + if x.dtype.kind == "M": # datetime # Same treatment will be applied to x_new. # Allow x_new.dtype==M8[D] and x.dtype==M8[ns], or vice versa x = x.astype("M8[ns]").astype(float) + elif x.dtype.kind == "m": # timedelta + x = x.astype("m8[ns]").astype(float) t = kernels.make_interp_knots(x, k, check_finite=False) if k < 2: @@ -181,15 +183,20 @@ def splev( if t.shape != (c.sizes[dim] + k + 1,): raise ValueError("Interpolated dimension has been sliced") - if x_new.dtype.kind == "M": + if x_new.dtype.kind == "M": # datetime # Note that we're modifying the x_new values, not the x_new coords - # xarray datetime objects are always in ns - x_new = x_new.astype(float) + x_new = x_new.astype("M8[ns]").astype(float) + elif x_new.dtype.kind == "m": # timedelta + x_new = x_new.astype("m8[ns]").astype(float) if extrapolate == "clip": x = tck.coords[dim].values - if x.dtype.kind == "M": + + if x.dtype.kind == "M": # datetime x = x.astype("M8[ns]").astype(float) + elif x.dtype.kind == "m": # timedelta + x = x.astype("m8[ns]").astype(float) + x_new = np.clip(x_new, x[0].tolist(), x[-1].tolist()) extrapolate = False diff --git a/xarray_extras/tests/test_interpolate.py b/xarray_extras/tests/test_interpolate.py index 8d5943c..ed3201d 100644 --- a/xarray_extras/tests/test_interpolate.py +++ b/xarray_extras/tests/test_interpolate.py @@ -192,8 +192,8 @@ def test_nonfloat(x_dtype, x_new_dtype): @pytest.mark.filterwarnings("ignore:Converting non-nanosecond precision datetime ") -@pytest.mark.parametrize("x_new_dtype", ["