Skip to content

Commit 5296ed1

Browse files
Raise error when datetime64 values that are outside the valid range for ns precision are converted to ns precision (#4454)
timedelta64 values outside the valid range will not currently raise an error, but will if pandas eventually makes that so. See pandas issue 36615. Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com>
1 parent f821fe2 commit 5296ed1

File tree

4 files changed

+24
-5
lines changed

4 files changed

+24
-5
lines changed

doc/whats-new.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ New Features
3434
Bug fixes
3535
~~~~~~~~~
3636

37+
- Fix bug where datetime64 times are silently changed to incorrect values if they are outside the valid date range for ns precision when provided in some other units (:issue:`4427`, :pull:`4454`).
38+
By `Andrew Pauling <https://github.com/andrewpauling>`_
3739
- Fix silently overwriting the `engine` key when passing :py:func:`open_dataset` a file object
3840
to an incompatible netCDF (:issue:`4457`). Now incompatible combinations of files and engines raise
3941
an exception instead. By `Alessandro Amici <https://github.com/alexamici>`_.

xarray/core/parallel.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,9 @@ def map_blocks(
255255
to the function being applied in ``xr.map_blocks()``:
256256
257257
>>> array.map_blocks(
258-
... calculate_anomaly, kwargs={"groupby_type": "time.year"}, template=array,
258+
... calculate_anomaly,
259+
... kwargs={"groupby_type": "time.year"},
260+
... template=array,
259261
... ) # doctest: +ELLIPSIS
260262
<xarray.DataArray (time: 24)>
261263
dask.array<calculate_anomaly-...-<this, shape=(24,), dtype=float64, chunksize=(24,), chunktype=numpy.ndarray>

xarray/core/variable.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,9 @@ def _maybe_wrap_data(data):
177177

178178
def _possibly_convert_objects(values):
179179
"""Convert arrays of datetime.datetime and datetime.timedelta objects into
180-
datetime64 and timedelta64, according to the pandas convention.
180+
datetime64 and timedelta64, according to the pandas convention. Also used for
181+
validating that datetime64 and timedelta64 objects are within the valid date
182+
range for ns precision, as pandas will raise an error if they are not.
181183
"""
182184
return np.asarray(pd.Series(values.ravel())).reshape(values.shape)
183185

@@ -238,16 +240,16 @@ def as_compatible_data(data, fastpath=False):
238240
'"1"'
239241
)
240242

241-
# validate whether the data is valid data types
243+
# validate whether the data is valid data types.
242244
data = np.asarray(data)
243245

244246
if isinstance(data, np.ndarray):
245247
if data.dtype.kind == "O":
246248
data = _possibly_convert_objects(data)
247249
elif data.dtype.kind == "M":
248-
data = np.asarray(data, "datetime64[ns]")
250+
data = _possibly_convert_objects(data)
249251
elif data.dtype.kind == "m":
250-
data = np.asarray(data, "timedelta64[ns]")
252+
data = _possibly_convert_objects(data)
251253

252254
return _maybe_wrap_data(data)
253255

xarray/tests/test_variable.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,19 @@ def test_object_conversion(self):
294294
actual = self.cls("x", data)
295295
assert actual.dtype == data.dtype
296296

297+
def test_datetime64_valid_range(self):
298+
data = np.datetime64("1250-01-01", "us")
299+
pderror = pd.errors.OutOfBoundsDatetime
300+
with raises_regex(pderror, "Out of bounds nanosecond"):
301+
self.cls(["t"], [data])
302+
303+
@pytest.mark.xfail(reason="pandas issue 36615")
304+
def test_timedelta64_valid_range(self):
305+
data = np.timedelta64("200000", "D")
306+
pderror = pd.errors.OutOfBoundsTimedelta
307+
with raises_regex(pderror, "Out of bounds nanosecond"):
308+
self.cls(["t"], [data])
309+
297310
def test_pandas_data(self):
298311
v = self.cls(["x"], pd.Series([0, 1, 2], index=[3, 2, 1]))
299312
assert_identical(v, v[[0, 1, 2]])

0 commit comments

Comments
 (0)