Stream: python-questions
Topic: timedelta support for nonstandard calendars
Heather Craker (Jul 07 2021 at 17:48):
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!
Deepak Cherian (Jul 07 2021 at 17:53):
Does https://github.com/pydata/xarray/discussions/4999 help?
Deepak Cherian (Jul 07 2021 at 18:09):
delta = cftime.datetime
Ah you're creating a datetime
not a timedelta
Heather Craker (Jul 07 2021 at 18:11):
Oh I see the problem now. Using datetime.timedelta
I can add one day to my cftime.datetime
object.
Heather Craker (Jul 07 2021 at 18:12):
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.
Rich Neale (Aug 04 2021 at 23:41):
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
Deepak Cherian (Aug 05 2021 at 17:14):
@Rich Neale can you describe what you're trying to do in more detail?
Rich Neale (Aug 09 2021 at 17:31):
Just to re-label (FEB) by 1 backwards (JAN) as par of the var.time.dt.strftime("%b")
Deepak Cherian (Aug 09 2021 at 20:30):
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")
Rich Neale (Aug 09 2021 at 23:06):
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") ?
Deepak Cherian (Aug 10 2021 at 14:44):
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: Jan 30 2022 at 12:01 UTC