Skip to content

Conversation

@spencerkclark
Copy link
Member

@spencerkclark spencerkclark commented Feb 22, 2020

  • Tests added
  • Passes isort -rc . && black . && mypy . && flake8
  • Fully documented, including whats-new.rst for all changes and api.rst for new API

This is particularly useful for removing microsecond noise that can sometimes be added from decoding times via cftime.num2date, though also applies more generally. The methods used here for rounding dates in the integer domain are copied from pandas.

On a somewhat more internal note, this adds an asi8 property to CFTimeIndex, which encodes the dates as integer values representing microseconds since 1970-01-01; this encoding is made exact via the exact_cftime_datetime_difference function. It's possible this could be useful in other contexts.

Some examples:

In [1]: import xarray as xr

In [2]: times = xr.cftime_range("2000", periods=5, freq="17D")

In [3]: time = xr.DataArray(times, dims=["time"], name="time")

In [4]: time.dt.floor("11D")
Out[4]:
<xarray.DataArray 'floor' (time: 5)>
array([cftime.DatetimeGregorian(1999-12-31 00:00:00),
       cftime.DatetimeGregorian(2000-01-11 00:00:00),
       cftime.DatetimeGregorian(2000-02-02 00:00:00),
       cftime.DatetimeGregorian(2000-02-13 00:00:00),
       cftime.DatetimeGregorian(2000-03-06 00:00:00)], dtype=object)
Coordinates:
  * time     (time) object 2000-01-01 00:00:00 ... 2000-03-09 00:00:00

In [5]: time.dt.ceil("11D")
Out[5]:
<xarray.DataArray 'ceil' (time: 5)>
array([cftime.DatetimeGregorian(2000-01-11 00:00:00),
       cftime.DatetimeGregorian(2000-01-22 00:00:00),
       cftime.DatetimeGregorian(2000-02-13 00:00:00),
       cftime.DatetimeGregorian(2000-02-24 00:00:00),
       cftime.DatetimeGregorian(2000-03-17 00:00:00)], dtype=object)
Coordinates:
  * time     (time) object 2000-01-01 00:00:00 ... 2000-03-09 00:00:00

In [6]: time.dt.round("11D")
Out[6]:
<xarray.DataArray 'round' (time: 5)>
array([cftime.DatetimeGregorian(1999-12-31 00:00:00),
       cftime.DatetimeGregorian(2000-01-22 00:00:00),
       cftime.DatetimeGregorian(2000-02-02 00:00:00),
       cftime.DatetimeGregorian(2000-02-24 00:00:00),
       cftime.DatetimeGregorian(2000-03-06 00:00:00)], dtype=object)
Coordinates:
  * time     (time) object 2000-01-01 00:00:00 ... 2000-03-09 00:00:00

Copy link
Contributor

@dcherian dcherian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @spencerkclark

I had a couple of minor suggestions but looks great otherwise.

  - Fix floating point issue in asi8 and add tests
  - Ensure dask only computes once when using the rounding accessors
@dcherian
Copy link
Contributor

dcherian commented Mar 2, 2020

Thanks @spencerkclark

@dcherian dcherian merged commit 45d88fc into pydata:master Mar 2, 2020
@spencerkclark spencerkclark deleted the cftimeindex-round-floor-ceil branch March 2, 2020 12:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants