diff --git a/xarray/coding/variables.py b/xarray/coding/variables.py index 83112628dbb..b036fd5dfb6 100644 --- a/xarray/coding/variables.py +++ b/xarray/coding/variables.py @@ -426,7 +426,10 @@ def encode(self, variable: Variable, name: T_Name = None): if fill_value is not None and has_unsigned: pop_to(encoding, attrs, "_Unsigned") # XXX: Is this actually needed? Doesn't the backend handle this? - data = duck_array_ops.astype(duck_array_ops.around(data), dtype) + signed_dtype = np.dtype(f"i{dtype.itemsize}") + data = duck_array_ops.view( + duck_array_ops.astype(duck_array_ops.around(data), signed_dtype), dtype + ) attrs["_FillValue"] = fill_value return Variable(dims, data, attrs, encoding, fastpath=True) diff --git a/xarray/core/duck_array_ops.py b/xarray/core/duck_array_ops.py index 7e7333fd8ea..be842b661c3 100644 --- a/xarray/core/duck_array_ops.py +++ b/xarray/core/duck_array_ops.py @@ -236,6 +236,16 @@ def astype(data, dtype, **kwargs): return data.astype(dtype, **kwargs) +def view(data, *args, **kwargs): + if hasattr(data, "__array_namespace__"): + xp = get_array_namespace(data) + if xp == np: + # numpy currently doesn't have a view: + return data.view(*args, **kwargs) + return xp.view(data, *args, **kwargs) + return data.view(*args, **kwargs) + + def asarray(data, xp=np, dtype=None): converted = data if is_duck_array(data) else xp.asarray(data)