cftime_range fails for base cftime.datetime object
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 4.2k
- Forks
- 1.4k
- Avg merge
- 2d 15h
- Merged PRs (30d)
- 14
Description
What happened:
xarray.cftime_range does not accept dates that use base classcftime.datetime objects.
What you expected to happen:
I expected xarray.cftime_range to raise an exception that this is an unsupported cftime.datetime type and for the documentation to reflect this.
Minimal Complete Verifiable Example:
import cftime
import xarray
date = cftime.datetime(10,1,1)
xarray.cftime_range(date, periods=3, freq='Y')
Anything else we need to know?:
Returns this error:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-29-d090ea15e436> in <module>
2 import xarray
3 date = cftime.datetime(10,1,1)
----> 4 xarray.cftime_range(date, periods=3, freq='Y')
/g/data3/hh5/public/apps/miniconda3/envs/analysis3-20.07/lib/python3.7/site-packages/xarray/coding/cftime_offsets.py in cftime_range(start, end, periods, freq, normalize, name, closed, calendar)
973 else:
974 offset = to_offset(freq)
--> 975 dates = np.array(list(_generate_range(start, end, periods, offset)))
976
977 left_closed = False
/g/data3/hh5/public/apps/miniconda3/envs/analysis3-20.07/lib/python3.7/site-packages/xarray/coding/cftime_offsets.py in _generate_range(start, end, periods, offset)
744 """
745 if start:
--> 746 start = offset.rollforward(start)
747
748 if end:
/g/data3/hh5/public/apps/miniconda3/envs/analysis3-20.07/lib/python3.7/site-packages/xarray/coding/cftime_offsets.py in rollforward(self, date)
526 def rollforward(self, date):
527 """Roll date forward to nearest end of year"""
--> 528 if self.onOffset(date):
529 return date
530 else:
/g/data3/hh5/public/apps/miniconda3/envs/analysis3-20.07/lib/python3.7/site-packages/xarray/coding/cftime_offsets.py in onOffset(self, date)
522 """Check if the given date is in the set of possible dates created
523 using a length-one version of this offset class."""
--> 524 return date.day == _days_in_month(date) and date.month == self.month
525
526 def rollforward(self, date):
/g/data3/hh5/public/apps/miniconda3/envs/analysis3-20.07/lib/python3.7/site-packages/xarray/coding/cftime_offsets.py in _days_in_month(date)
195 else:
196 reference = type(date)(date.year, date.month + 1, 1)
--> 197 return (reference - timedelta(days=1)).day
198
199
TypeError: unsupported operand type(s) for -: 'cftime._cftime.datetime' and 'datetime.timedelta'
Works if a datetime object with a calendar is used:
import cftime
import xarray
date = cftime.DatetimeGregorian(10,1,1)
xarray.cftime_range(date, periods=3, freq='Y')
Returns:
CFTimeIndex([0010-12-31 00:00:00, 0011-12-31 00:00:00, 0012-12-31 00:00:00], dtype='object')
as expected.
The error occurs here
https://github.com/pydata/xarray/blob/master/xarray/coding/cftime_offsets.py#L197
because this operation is not defined for the base class
https://github.com/Unidata/cftime/blob/master/cftime/_cftime.pyx#L1054
The relevant tests all seem to use datetime strings which are by default standard calendar:
https://github.com/pydata/xarray/blob/master/xarray/coding/cftime_offsets.py#L788
Environment:
Output of xr.show_versions()
INSTALLED VERSIONS
commit: None
python: 3.7.8 | packaged by conda-forge | (default, Jul 31 2020, 02:25:08)
[GCC 7.5.0]
python-bits: 64
OS: Linux
OS-release: 2.6.32-754.18.2.el6.x86_64
machine: x86_64
processor: x86_64
byteorder: little
LC_ALL: en_AU.utf8
LANG: en_AU.UTF-8
LOCALE: en_AU.UTF-8
libhdf5: 1.10.5
libnetcdf: 4.7.4
xarray: 0.16.0
pandas: 1.1.0
numpy: 1.19.1
scipy: 1.5.2
netCDF4: 1.5.3
pydap: installed
h5netcdf: 0.8.1
h5py: 2.10.0
Nio: 1.5.5
zarr: 2.4.0
cftime: 1.0.3.4
nc_time_axis: 1.2.0
PseudoNetCDF: None
rasterio: 1.1.5
cfgrib: 0.9.8.4
iris: 2.4.0
bottleneck: 1.3.2
dask: 2.22.0
distributed: 2.22.0
matplotlib: 3.3.0
cartopy: 0.18.0
seaborn: 0.10.1
numbagg: None
pint: 0.14
setuptools: 49.2.0.post20200712
pip: 20.1.1
conda: installed
pytest: 6.0.1
IPython: 7.17.0
sphinx: 3.2.0
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with xarray/coding/cftime_offsets.py around _days_in_month at line 197 and reproduce the cftime.datetime example from the issue. Review the related tests around line 788, then ensure the unsupported base cftime.datetime case has the documented exception behavior and corresponding documentation coverage.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- data
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 48/100