Skip to content

Commit 8f3a302

Browse files
authored
fix regression in time-like check when decoding masked data (#8277)
* fix regression in time-like check when decoding masked data * add test * use _unpack_netcdf_time_units to check for proper units-string * test with decode_times
1 parent e611c97 commit 8f3a302

File tree

3 files changed

+29
-2
lines changed

3 files changed

+29
-2
lines changed

doc/whats-new.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ Bug fixes
6262
- :py:meth:`DataArray.rename` & :py:meth:`Dataset.rename` would emit a warning
6363
when the operation was a no-op. (:issue:`8266`)
6464
By `Simon Hansen <https://github.com/hoxbro>`_.
65+
- Fixed a regression introduced in the previous release checking time-like units
66+
when encoding/decoding masked data (:issue:`8269`, :pull:`8277`).
67+
By `Kai Mühlbauer <https://github.com/kmuehlbauer>`_.
6568

6669
- Fix datetime encoding precision loss regression introduced in the previous
6770
release for datetimes encoded with units requiring floating point values, and

xarray/coding/variables.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,9 @@ def _apply_mask(
217217

218218
def _is_time_like(units):
219219
# test for time-like
220+
if units is None:
221+
return False
220222
time_strings = [
221-
"since",
222223
"days",
223224
"hours",
224225
"minutes",
@@ -227,7 +228,19 @@ def _is_time_like(units):
227228
"microseconds",
228229
"nanoseconds",
229230
]
230-
return any(tstr in str(units) for tstr in time_strings)
231+
units = str(units)
232+
# to prevent detecting units like `days accumulated` as time-like
233+
# special casing for datetime-units and timedelta-units (GH-8269)
234+
if "since" in units:
235+
from xarray.coding.times import _unpack_netcdf_time_units
236+
237+
try:
238+
_unpack_netcdf_time_units(units)
239+
except ValueError:
240+
return False
241+
return True
242+
else:
243+
return any(tstr == units for tstr in time_strings)
231244

232245

233246
class CFMaskCoder(VariableCoder):

xarray/tests/test_conventions.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,17 @@ def test_invalid_time_units_raises_eagerly(self) -> None:
333333
with pytest.raises(ValueError, match=r"unable to decode time"):
334334
decode_cf(ds)
335335

336+
@pytest.mark.parametrize("decode_times", [True, False])
337+
def test_invalid_timedelta_units_do_not_decode(self, decode_times) -> None:
338+
# regression test for #8269
339+
ds = Dataset(
340+
{"time": ("time", [0, 1, 20], {"units": "days invalid", "_FillValue": 20})}
341+
)
342+
expected = Dataset(
343+
{"time": ("time", [0.0, 1.0, np.nan], {"units": "days invalid"})}
344+
)
345+
assert_identical(expected, decode_cf(ds, decode_times=decode_times))
346+
336347
@requires_cftime
337348
def test_dataset_repr_with_netcdf4_datetimes(self) -> None:
338349
# regression test for #347

0 commit comments

Comments
 (0)