Skip to content

Commit c2a6902

Browse files
spencerkclarkshoyer
authored andcommitted
Fix bug where OverflowError is not being raised (#2519)
1 parent 2f0096c commit c2a6902

File tree

3 files changed

+25
-2
lines changed

3 files changed

+25
-2
lines changed

doc/whats-new.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ Bug fixes
123123
By `Spencer Clark <https://github.com/spencerkclark>`_.
124124
- Avoid use of Dask's deprecated ``get=`` parameter in tests
125125
by `Matthew Rocklin <https://github.com/mrocklin/>`_.
126+
- An ``OverflowError`` is now accurately raised and caught during the
127+
encoding process if a reference date is used that is so distant that
128+
the dates must be encoded using cftime rather than NumPy (:issue:`2272`).
129+
By `Spencer Clark <https://github.com/spencerkclark>`_.
126130

127131
.. _whats-new.0.10.9:
128132

xarray/coding/times.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,12 @@ def encode_cf_datetime(dates, units=None, calendar=None):
361361
delta_units = _netcdf_to_numpy_timeunit(delta)
362362
time_delta = np.timedelta64(1, delta_units).astype('timedelta64[ns]')
363363
ref_date = np.datetime64(pd.Timestamp(ref_date))
364-
num = (dates - ref_date) / time_delta
364+
365+
# Wrap the dates in a DatetimeIndex to do the subtraction to ensure
366+
# an OverflowError is raised if the ref_date is too far away from
367+
# dates to be encoded (GH 2272).
368+
num = (pd.DatetimeIndex(dates.ravel()) - ref_date) / time_delta
369+
num = num.values.reshape(dates.shape)
365370

366371
except (OutOfBoundsDatetime, OverflowError):
367372
num = _encode_datetime_with_cftime(dates, units, calendar)

xarray/tests/test_coding_times.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
import pytest
99

1010
from xarray import DataArray, Variable, coding, decode_cf, set_options
11-
from xarray.coding.times import _import_cftime
11+
from xarray.coding.times import (_import_cftime, decode_cf_datetime,
12+
encode_cf_datetime)
1213
from xarray.coding.variables import SerializationWarning
1314
from xarray.core.common import contains_cftime_datetimes
1415

@@ -763,3 +764,16 @@ def test_contains_cftime_datetimes_non_cftimes(non_cftime_data):
763764
@pytest.mark.parametrize('non_cftime_data', [DataArray([]), DataArray([1, 2])])
764765
def test_contains_cftime_datetimes_non_cftimes_dask(non_cftime_data):
765766
assert not contains_cftime_datetimes(non_cftime_data.chunk())
767+
768+
769+
@pytest.mark.skipif(not has_cftime_or_netCDF4, reason='cftime not installed')
770+
@pytest.mark.parametrize('shape', [(24,), (8, 3), (2, 4, 3)])
771+
def test_encode_datetime_overflow(shape):
772+
# Test for fix to GH 2272
773+
dates = pd.date_range('2100', periods=24).values.reshape(shape)
774+
units = 'days since 1800-01-01'
775+
calendar = 'standard'
776+
777+
num, _, _ = encode_cf_datetime(dates, units, calendar)
778+
roundtrip = decode_cf_datetime(num, units, calendar)
779+
np.testing.assert_array_equal(dates, roundtrip)

0 commit comments

Comments
 (0)