Hi all. I'm trying to do some timedelta operations on cftime.datetime
objects so I can write a computation function that supports non-standard calendars (i.e noleap
, all_leap
, julian
, etc.). All I need to do is be able to add one day to a preexisting cftime.datetime
object. The documentation page for cftime.datetime
says the following:
This class mimics datetime.datetime but support calendars other than the proleptic Gregorian calendar.
Supports timedelta operations by overloading +/-, and comparisons with other instances using the same calendar.
I don't think the +
and -
operators are actually overloaded, because I recieve a TypeError when I run the code below. On top of that, there is no way to define one day in cftime
since the month must be between 1 and 12.
time = cftime.datetime(year=2000, month=1, day=1, calendar='gregorian') delta = cftime.datetime(year=0, month=1, day=1, calendar='gregorian', has_year_zero=True) print(time + delta)
TypeError: unsupported operand type(s) for +: 'cftime._cftime.datetime' and 'cftime._cftime.datetime'
Does anyone now if there is an existing package that supports this kind of operation? Pandas has timedeltas and datetime offsets, but it only supports one kind of calendar. Any help is appreciated! Thanks!
Does https://github.com/pydata/xarray/discussions/4999 help?
delta = cftime.datetime
Ah you're creating a datetime
not a timedelta
Oh I see the problem now. Using datetime.timedelta
I can add one day to my cftime.datetime
object.
I just remembered that I have another case where I will need to add a month to a datetime, but datetime.timedelta
does not support months. Do you know of something that does? Depending on which month is next, I want to add 28, 29, 30, or 31 days.
I want to do this too!
I tried this package and couldn't get it to work.
https://stackoverflow.com/questions/12433233/what-is-the-difference-between-datetime-timedelta-and-dateutil-relativedelta
@Rich Neale can you describe what you're trying to do in more detail?
Just to re-label (FEB) by 1 backwards (JAN) as par of the var.time.dt.strftime("%b")
is the time vector always starting at day 1 of the month? If so, does this work
(var.time - pd.Timedelta("1 day")).dt.strftime("%b")
Oh sorry, no. Knowing the name of the month from the time object (var.time) I want to realign the time object to be one month earlier. Can I just do pd.timedelta("1 month") ?
Unfortunately not, because pd.timedelta
tries to convert that to an absolute number of nanoseconds, which fails ...
But how about this:
time = xr.DataArray(
xr.cftime_range("1000-01-01", "1000-05-01", freq="MS", calendar="360_day"), dims="time", name="time"
)
time - xr.coding.cftime_offsets.MonthEnd(1)
Does this do what you want? If so, I can open an issue about making those offsets more public
Last updated: May 16 2025 at 17:14 UTC