Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
8cc942e
added a on_error flag to CFDatetimeCoder -- and tests for it.
ChrisBarker-NOAA Feb 5, 2026
6598b3a
fixed bug in test
ChrisBarker-NOAA Feb 6, 2026
afa6204
added a on_error flag to CFDatetimeCoder -- and tests for it.
ChrisBarker-NOAA Feb 5, 2026
8af06c2
fixed bug in test
ChrisBarker-NOAA Feb 6, 2026
1082fba
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 6, 2026
adddce0
Merge branch 'warn_on_time_error' of https://github.com/ChrisBarker-N…
ChrisBarker-NOAA Feb 7, 2026
318b93e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 7, 2026
4b65e9d
Merge branch 'main' into warn_on_time_error
ChrisBarker-NOAA Apr 14, 2026
f548349
Merge remote-tracking branch 'upstream/main' into warn_on_time_error
ChrisBarker-NOAA Apr 28, 2026
5ef0841
dded flags for conventions decode_cdf_variable -- start of tesdded fl…
ChrisBarker-NOAA Apr 28, 2026
c943e71
tests for all flags for decode_cf_variable.
ChrisBarker-NOAA Apr 29, 2026
e79b239
added the decode_times flags to open_dataset, with full tests.
ChrisBarker-NOAA May 1, 2026
24961f1
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 1, 2026
5f88b4b
clean up some docstrings
ChrisBarker-NOAA May 1, 2026
9f05f51
Merge remote-tracking branch 'origin/warn_on_time_error' into warn_on…
ChrisBarker-NOAA May 1, 2026
bee2927
fixed type hints
ChrisBarker-NOAA May 2, 2026
b965411
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 2, 2026
274bb60
a couple more type hint fixes.
ChrisBarker-NOAA May 4, 2026
a98dfda
Merge branch 'main' into warn_on_time_error
kmuehlbauer May 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 22 additions & 3 deletions xarray/coding/times.py
Original file line number Diff line number Diff line change
Expand Up @@ -1370,15 +1370,24 @@ class CFDatetimeCoder(VariableCoder):
May not be supported by all the backends.
time_unit : PDDatetimeUnitOptions
Target resolution when decoding dates. Defaults to "ns".
on_error : str, optional
What to do if there is an error when attempting to decode
a time variable. Options are: "raise", "warn", "ignore".
Defaults to "raise".
"""

def __init__(
self,
use_cftime: bool | None = None,
time_unit: PDDatetimeUnitOptions = "ns",
on_error: str = "raise",
) -> None:
self.use_cftime = use_cftime
self.time_unit = time_unit
if on_error in {"raise", "warn", "ignore"}:
self.on_error = on_error
else:
raise ValueError('on_error must be one of "raise", "warn", "ignore")')

def encode(self, variable: Variable, name: T_Name = None) -> Variable:
if np.issubdtype(variable.dtype, np.datetime64) or contains_cftime_datetimes(
Expand Down Expand Up @@ -1411,9 +1420,19 @@ def decode(self, variable: Variable, name: T_Name = None) -> Variable:

units = pop_to(attrs, encoding, "units")
calendar = pop_to(attrs, encoding, "calendar")
dtype = _decode_cf_datetime_dtype(
data, units, calendar, self.use_cftime, self.time_unit
)
try:
dtype = _decode_cf_datetime_dtype(
data, units, calendar, self.use_cftime, self.time_unit
)
except ValueError as err:
if self.on_error == "ignore":
return variable
elif self.on_error == "warn":
emit_user_level_warning(err.args[0])
return variable
else:
raise

transform = partial(
decode_cf_datetime,
units=units,
Expand Down
17 changes: 16 additions & 1 deletion xarray/conventions.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,22 @@ def decode_cf_variable(
" ds = xr.open_dataset(decode_times=time_coder)\n",
FutureWarning,
)
decode_times = CFDatetimeCoder(use_cftime=use_cftime)
# decode_times = CFDatetimeCoder(use_cftime=use_cftime)
decode_times_options = {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe this dict should be a global?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, in xarray/core/types.py somewhere nearby CFCalendar would be nice.

True: "raise",
"error": "raise",
"ignore": "ignore",
"warn": "warn",
}
try:
on_error = decode_times_options[decode_times]
except KeyError:
raise ValueError(
"`decode_times` must be one of:"
"True, False, 'raise', 'warn', 'ignore'"
) from None
decode_times = CFDatetimeCoder(use_cftime=use_cftime, on_error=on_error)

elif use_cftime is not None:
raise TypeError(
"Usage of 'use_cftime' as a kwarg is not allowed "
Expand Down
54 changes: 54 additions & 0 deletions xarray/tests/test_coding_times.py
Original file line number Diff line number Diff line change
Expand Up @@ -2229,3 +2229,57 @@ def test_roundtrip_empty_datetime64_array(time_unit: PDDatetimeUnitOptions) -> N
)
assert_identical(variable, roundtripped)
assert roundtripped.dtype == variable.dtype


@requires_cftime
def test_on_error_raises():
"""
By default, decoding errors should raise
"""
array = np.array([0, 1, 2], dtype=np.dtype("int64"))
encoded = Variable(["time"], array, attrs={"units": "ms since 00:00:00"})

# default is "raise"
coder = CFDatetimeCoder()

with pytest.raises(ValueError):
coder.decode(encoded)

# setting to "raise" should do the same thing.
coder = CFDatetimeCoder(on_error="raise")

with pytest.raises(ValueError):
coder.decode(encoded)


@requires_cftime
def test_on_error_ignore():
"""
If on_error="ignore", no change.
"""
array = np.array([0, 1, 2], dtype=np.dtype("int64"))
encoded = Variable(["time"], array, attrs={"units": "ms since 00:00:00"})

coder = CFDatetimeCoder(on_error="ignore")

decoded = coder.decode(encoded)

# it shouldn't have changed the variable
assert decoded is encoded


@requires_cftime
def test_on_error_warn():
"""
If on_error="warn", no change, with a warning.
"""
array = np.array([0, 1, 2], dtype=np.dtype("int64"))
encoded = Variable(["time"], array, attrs={"units": "ms since 00:00:00"})

coder = CFDatetimeCoder(on_error="warn")

with pytest.warns(UserWarning, match="unable to decode time units"):
decoded = coder.decode(encoded)

# it shouldn't have changed the variable
assert decoded is encoded
Loading