Unidata / cftime

Time-handling functionality from netcdf4-python.

Home Page:https://unidata.github.io/cftime

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

cftime.datetime does not allow addition

mcgibbon opened this issue · comments

cftime.datetime returns an object of type cftime._cftime.datetime, which cannot be added to or subtracted from using a timedelta. Based on its calendar keyword argument, I would expect it to return a subclass such as DatetimeJulian which has arithmetic defined.

Python 3.7.4 (default, Aug 13 2019, 15:17:50)
[Clang 4.0.1 (tags/RELEASE_401/final)] :: Anaconda, Inc. on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import cftime
>>> dt = cftime.datetime(2020, 1, 1, calendar="julian")
>>> from datetime import timedelta
>>> dt += timedelta(hours=1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +=: 'cftime._cftime.datetime' and 'datetime.timedelta'
>>> cftime.__version__
'1.2.1'

Based on its calendar keyword argument, I would expect it to return a subclass such as DatetimeJulian which has arithmetic defined.

I would be +1 on this. It's often quite useful to be able to construct datetimes starting from a string calendar name rather than an explicit cftime type, which extending the constructor of cftime.datetime in this way would enable. E.g. in lieu of this we need to use logic like this in xarray.

Pull request would be welcomed.

PR #199 implements this by changing the name of the base class datetime to datetime_base and making datetime a factory function that returns calendar-specific datetime instances.

PR #201 is an alternate fix that does not require changing the name of the base class. It does require changing the default calendar from "standard" to None. Since much of the code is moved from cython to pure python for this solution, it is quite a bit slower. More optimization is needed before it can be merged.

PR #202 is yet another alternate fix that does not require changing the name of the base class, nor does it degrade performance by migrating the base class to python. It creates 'calendar-aware' instances of the base-class directly using the calendar kwarg to __init__ and a bunch if if/else statements in __add__ and __sub__. The sub-classes are still there, although they are just stubs that no longer over-ride any methods of the base class. This should work fine as long as no one is checking for the subclass type directly (instead of just checking the value of the calendar attribute).

xarray tests pass with PR #202. nc-time-axis requires a small change to the tests.

PR #202 is my preferred solution to this issue. It doesn't sacrifice any performance, and probably will have the least impact on existing code.

closed by PR #202