From fb97fec3e48efa82e42326fa07ebdf4f381eba17 Mon Sep 17 00:00:00 2001 From: Spencer Clark Date: Fri, 4 Jan 2019 16:53:15 -0500 Subject: [PATCH 1/2] Convert ref_date to UTC in encode_cf_datetime --- doc/whats-new.rst | 5 ++++- xarray/coding/times.py | 2 +- xarray/tests/test_coding_times.py | 16 ++++++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index 27d0dc615d2..bfe6e57e3bc 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -39,7 +39,10 @@ Bug fixes as an argument to ``scipy.interpolate.interp1d``, allowing for interpolation from higher frequencies to lower frequencies. Datapoints outside the bounds of the original time coordinate are now filled with NaN (:issue:`2197`). By - `Spencer Clark `_. + `Spencer Clark `_. +- Saving files with times encoded with reference dates with timezones + (e.g. '2000-01-01T00:00:00-05:00') no longer raises an error + (:issue:`2649`). By `Spencer Clark `_. .. _whats-new.0.11.2: diff --git a/xarray/coding/times.py b/xarray/coding/times.py index 0f2045cf356..a68689564d9 100644 --- a/xarray/coding/times.py +++ b/xarray/coding/times.py @@ -357,7 +357,7 @@ def encode_cf_datetime(dates, units=None, calendar=None): delta_units = _netcdf_to_numpy_timeunit(delta) time_delta = np.timedelta64(1, delta_units).astype('timedelta64[ns]') - ref_date = pd.Timestamp(ref_date) + ref_date = pd.Timestamp(ref_date).tz_convert(None) # Wrap the dates in a DatetimeIndex to do the subtraction to ensure # an OverflowError is raised if the ref_date is too far away from diff --git a/xarray/tests/test_coding_times.py b/xarray/tests/test_coding_times.py index d9a40c23add..198f40ae410 100644 --- a/xarray/tests/test_coding_times.py +++ b/xarray/tests/test_coding_times.py @@ -750,3 +750,19 @@ def test_encode_cf_datetime_pandas_min(): np.testing.assert_array_equal(num, expected_num) assert units == expected_units assert calendar == expected_calendar + + +def test_encode_cf_datetime_units_with_tz(): + # Regression test for GH 2649 + units = 'days since 2000-01-01T00:00:00-05:00' + calendar = 'proleptic_gregorian' + dates = pd.date_range('2000', periods=3, tz='US/Eastern').values + num, units, calendar = encode_cf_datetime(dates, + units=units, + calendar=calendar) + expected_num = np.array([0, 1, 2]) + expected_units = 'days since 2000-01-01T00:00:00-05:00' + expected_calendar = 'proleptic_gregorian' + np.testing.assert_array_equal(num, expected_num) + assert units == expected_units + assert calendar == expected_calendar From 1e1ddb299a267c5a810de27f8f26ddae3daada36 Mon Sep 17 00:00:00 2001 From: Spencer Clark Date: Fri, 4 Jan 2019 20:07:00 -0500 Subject: [PATCH 2/2] Only convert ref_date if it is not timezone-naive --- xarray/coding/times.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/xarray/coding/times.py b/xarray/coding/times.py index a68689564d9..c337a42e3b4 100644 --- a/xarray/coding/times.py +++ b/xarray/coding/times.py @@ -357,7 +357,12 @@ def encode_cf_datetime(dates, units=None, calendar=None): delta_units = _netcdf_to_numpy_timeunit(delta) time_delta = np.timedelta64(1, delta_units).astype('timedelta64[ns]') - ref_date = pd.Timestamp(ref_date).tz_convert(None) + ref_date = pd.Timestamp(ref_date) + + # If the ref_date Timestamp is timezone-aware, convert to UTC and + # make it timezone-naive (GH 2649). + if ref_date.tz is not None: + ref_date = ref_date.tz_convert(None) # Wrap the dates in a DatetimeIndex to do the subtraction to ensure # an OverflowError is raised if the ref_date is too far away from