Skip to content

Commit b14e2d8

Browse files
aulemahalmathausespencerkclarkIllviljan
authored
Calendar utilities (#5233)
* dt.calendar and date_range * Migrate calendar utils from xclim | add dt.calendar * upd whats new * skip calendar tests with no cftime * add requires cftime 1.1.0 * import date_ranges in main * Apply suggestions from code review Co-authored-by: Mathias Hauser <[email protected]> * Add docs - use already existing is np datetime func * update from suggestions * Apply suggestions from code review Co-authored-by: Spencer Clark <[email protected]> * Modifications following review * Add DataArray and Dataset methods * use proper type annotation * Apply suggestions from code review Co-authored-by: Spencer Clark <[email protected]> * some more modifications after review * Apply suggestions from code review The code will break with this commit. Variable renaming to be done throughout all functions. Co-authored-by: Spencer Clark <[email protected]> * Finish applying suggestions from review * Put back missing @require_cftime * Apply suggestions from code review Co-authored-by: Spencer Clark <[email protected]> * Add tests - few fixes * wrap docstrings * Change way of importing/testing for cftime * Upd the weather-climate doc page * fix doc examples * Neat docs * fix in tests after review * Apply suggestions from code review Co-authored-by: Spencer Clark <[email protected]> * Better explain missing in notes - copy changes to obj methods * Apply suggestions from code review Co-authored-by: Spencer Clark <[email protected]> * Remove unused import Co-authored-by: Mathias Hauser <[email protected]> Co-authored-by: Spencer Clark <[email protected]> Co-authored-by: Illviljan <[email protected]>
1 parent f85ec66 commit b14e2d8

15 files changed

+1468
-41
lines changed

doc/api-hidden.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
core.accessor_dt.DatetimeAccessor.floor
7878
core.accessor_dt.DatetimeAccessor.round
7979
core.accessor_dt.DatetimeAccessor.strftime
80+
core.accessor_dt.DatetimeAccessor.calendar
8081
core.accessor_dt.DatetimeAccessor.date
8182
core.accessor_dt.DatetimeAccessor.day
8283
core.accessor_dt.DatetimeAccessor.dayofweek

doc/api.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ Dataset contents
109109
Dataset.drop_dims
110110
Dataset.set_coords
111111
Dataset.reset_coords
112+
Dataset.convert_calendar
113+
Dataset.interp_calendar
112114
Dataset.get_index
113115

114116
Comparisons
@@ -308,6 +310,8 @@ DataArray contents
308310
DataArray.drop_duplicates
309311
DataArray.reset_coords
310312
DataArray.copy
313+
DataArray.convert_calendar
314+
DataArray.interp_calendar
311315
DataArray.get_index
312316
DataArray.astype
313317
DataArray.item
@@ -526,6 +530,7 @@ Datetimelike properties
526530
DataArray.dt.season
527531
DataArray.dt.time
528532
DataArray.dt.date
533+
DataArray.dt.calendar
529534
DataArray.dt.is_month_start
530535
DataArray.dt.is_month_end
531536
DataArray.dt.is_quarter_end
@@ -1064,6 +1069,8 @@ Creating custom indexes
10641069
:toctree: generated/
10651070

10661071
cftime_range
1072+
date_range
1073+
date_range_like
10671074

10681075
Faceting
10691076
--------

doc/user-guide/weather-climate.rst

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,23 @@ using the same formatting as the standard `datetime.strftime`_ convention .
127127
dates.strftime("%c")
128128
da["time"].dt.strftime("%Y%m%d")
129129
130+
Conversion between non-standard calendar and to/from pandas DatetimeIndexes is
131+
facilitated with the :py:meth:`xarray.Dataset.convert_calendar` method (also available as
132+
:py:meth:`xarray.DataArray.convert_calendar`). Here, like elsewhere in xarray, the ``use_cftime``
133+
argument controls which datetime backend is used in the output. The default (``None``) is to
134+
use `pandas` when possible, i.e. when the calendar is standard and dates are within 1678 and 2262.
135+
136+
.. ipython:: python
137+
138+
dates = xr.cftime_range(start="2001", periods=24, freq="MS", calendar="noleap")
139+
da_nl = xr.DataArray(np.arange(24), coords=[dates], dims=["time"], name="foo")
140+
da_std = da.convert_calendar("standard", use_cftime=True)
141+
142+
The data is unchanged, only the timestamps are modified. Further options are implemented
143+
for the special ``"360_day"`` calendar and for handling missing dates. There is also
144+
:py:meth:`xarray.Dataset.interp_calendar` (and :py:meth:`xarray.DataArray.interp_calendar`)
145+
for `interpolating` data between calendars.
146+
130147
For data indexed by a :py:class:`~xarray.CFTimeIndex` xarray currently supports:
131148

132149
- `Partial datetime string indexing`_:
@@ -150,7 +167,8 @@ For data indexed by a :py:class:`~xarray.CFTimeIndex` xarray currently supports:
150167

151168
- Access of basic datetime components via the ``dt`` accessor (in this case
152169
just "year", "month", "day", "hour", "minute", "second", "microsecond",
153-
"season", "dayofyear", "dayofweek", and "days_in_month"):
170+
"season", "dayofyear", "dayofweek", and "days_in_month") with the addition
171+
of "calendar", absent from pandas:
154172

155173
.. ipython:: python
156174
@@ -160,6 +178,7 @@ For data indexed by a :py:class:`~xarray.CFTimeIndex` xarray currently supports:
160178
da.time.dt.dayofyear
161179
da.time.dt.dayofweek
162180
da.time.dt.days_in_month
181+
da.time.dt.calendar
163182
164183
- Rounding of datetimes to fixed frequencies via the ``dt`` accessor:
165184

@@ -214,30 +233,6 @@ For data indexed by a :py:class:`~xarray.CFTimeIndex` xarray currently supports:
214233
215234
da.resample(time="81T", closed="right", label="right", base=3).mean()
216235
217-
.. note::
218-
219-
220-
For some use-cases it may still be useful to convert from
221-
a :py:class:`~xarray.CFTimeIndex` to a :py:class:`pandas.DatetimeIndex`,
222-
despite the difference in calendar types. The recommended way of doing this
223-
is to use the built-in :py:meth:`~xarray.CFTimeIndex.to_datetimeindex`
224-
method:
225-
226-
.. ipython:: python
227-
:okwarning:
228-
229-
modern_times = xr.cftime_range("2000", periods=24, freq="MS", calendar="noleap")
230-
da = xr.DataArray(range(24), [("time", modern_times)])
231-
da
232-
datetimeindex = da.indexes["time"].to_datetimeindex()
233-
da["time"] = datetimeindex
234-
235-
However in this case one should use caution to only perform operations which
236-
do not depend on differences between dates (e.g. differentiation,
237-
interpolation, or upsampling with resample), as these could introduce subtle
238-
and silent errors due to the difference in calendar types between the dates
239-
encoded in your data and the dates stored in memory.
240-
241236
.. _Timestamp-valid range: https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#timestamp-limitations
242237
.. _ISO 8601 standard: https://en.wikipedia.org/wiki/ISO_8601
243238
.. _partial datetime string indexing: https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#partial-string-indexing

doc/whats-new.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,8 @@ New Features
156156
- Added ``storage_options`` argument to :py:meth:`to_zarr` (:issue:`5601`, :pull:`5615`).
157157
By `Ray Bell <https://github.com/raybellwaves>`_, `Zachary Blackwood <https://github.com/blackary>`_ and
158158
`Nathan Lis <https://github.com/wxman22>`_.
159+
- Added calendar utilities :py:func:`DataArray.convert_calendar`, :py:func:`DataArray.interp_calendar`, :py:func:`date_range`, :py:func:`date_range_like` and :py:attr:`DataArray.dt.calendar` (:issue:`5155`, :pull:`5233`).
160+
By `Pascal Bourgault <https://github.com/aulemahal>`_.
159161
- Histogram plots are set with a title displaying the scalar coords if any, similarly to the other plots (:issue:`5791`, :pull:`5792`).
160162
By `Maxime Liquet <https://github.com/maximlt>`_.
161163
- Slice plots display the coords units in the same way as x/y/colorbar labels (:pull:`5847`).

xarray/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
)
1010
from .backends.rasterio_ import open_rasterio
1111
from .backends.zarr import open_zarr
12-
from .coding.cftime_offsets import cftime_range
12+
from .coding.cftime_offsets import cftime_range, date_range, date_range_like
1313
from .coding.cftimeindex import CFTimeIndex
1414
from .coding.frequencies import infer_freq
1515
from .conventions import SerializationWarning, decode_cf
@@ -65,6 +65,8 @@
6565
"combine_by_coords",
6666
"combine_nested",
6767
"concat",
68+
"date_range",
69+
"date_range_like",
6870
"decode_cf",
6971
"dot",
7072
"cov",

0 commit comments

Comments
 (0)