From 42ed6d30e81dce5b9922ac82f76c5b3cd748b19e Mon Sep 17 00:00:00 2001 From: Justus Magin Date: Fri, 28 Jun 2024 10:18:55 +0200 Subject: [PATCH] promote floating-point numeric datetimes to 64-bit before decoding (#9182) * promote floating-point dates to 64-bit while decoding * add a test to make sure we don't regress * whats-new entry --- doc/whats-new.rst | 2 ++ xarray/coding/times.py | 2 ++ xarray/tests/test_coding_times.py | 16 ++++++++++++++++ 3 files changed, 20 insertions(+) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index 97631b4c324..c58f73cb1fa 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -37,6 +37,8 @@ Bug fixes ~~~~~~~~~ - Make :py:func:`testing.assert_allclose` work with numpy 2.0 (:issue:`9165`, :pull:`9166`). By `Pontus Lurcock `_. +- Promote floating-point numeric datetimes before decoding (:issue:`9179`, :pull:`9182`). + By `Justus Magin `_. Documentation diff --git a/xarray/coding/times.py b/xarray/coding/times.py index 466e847e003..34d4f9a23ad 100644 --- a/xarray/coding/times.py +++ b/xarray/coding/times.py @@ -278,6 +278,8 @@ def _decode_datetime_with_pandas( # timedelta64 value, and therefore would raise an error in the lines above. if flat_num_dates.dtype.kind in "iu": flat_num_dates = flat_num_dates.astype(np.int64) + elif flat_num_dates.dtype.kind in "f": + flat_num_dates = flat_num_dates.astype(np.float64) # Cast input ordinals to integers of nanoseconds because pd.to_timedelta # works much faster when dealing with integers (GH 1399). diff --git a/xarray/tests/test_coding_times.py b/xarray/tests/test_coding_times.py index 09221d66066..393f8400c46 100644 --- a/xarray/tests/test_coding_times.py +++ b/xarray/tests/test_coding_times.py @@ -1182,6 +1182,22 @@ def test_decode_0size_datetime(use_cftime): np.testing.assert_equal(expected, actual) +def test_decode_float_datetime(): + num_dates = np.array([1867128, 1867134, 1867140], dtype="float32") + units = "hours since 1800-01-01" + calendar = "standard" + + expected = np.array( + ["2013-01-01T00:00:00", "2013-01-01T06:00:00", "2013-01-01T12:00:00"], + dtype="datetime64[ns]", + ) + + actual = decode_cf_datetime( + num_dates, units=units, calendar=calendar, use_cftime=False + ) + np.testing.assert_equal(actual, expected) + + @requires_cftime def test_scalar_unit() -> None: # test that a scalar units (often NaN when using to_netcdf) does not raise an error