Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consequences of changing the default calendar in cftime.datetime #173

Closed
davidhassell opened this issue May 14, 2020 · 4 comments · Fixed by #174
Closed

Consequences of changing the default calendar in cftime.datetime #173

davidhassell opened this issue May 14, 2020 · 4 comments · Fixed by #174

Comments

@davidhassell
Copy link
Contributor

If I set a non-gregorian calendar in the initialization of a cftime.datetime object, then it is ignored in the daysinmonth calculation:

In [1]: import cftime

In [2]: cftime.__version__
Out[2]: '1.1.3'

In [3]: d = cftime.datetime(2000, 3, 3, calendar='360_day')

In [4]: d.calendar
Out[4]: '360_day'

In [5]: d.daysinmonth
Out[5]: 31

This is surprising! The dayofwk attribute does indeed take the calendar into account.

On a related note, is it still possible to encode a datetime with an unspecified calendar. This was possible when the default calendar was '', and was extremely useful for encoding a datetime that is meant to be interpreted in the context of one or calendars that are not yet known. At inspection time, the calendar value of '' tells my code to define a new datetime in the appropriate calendar so that comparisons can be made. I can't set calendar='', as other things break (as expected):

In [31]: e = cftime.datetime(2000, 3, 4, calendar='')

In [32]: e.timetuple()

ValueError: unsupported calendar

Is cftime.datetime any different, now, to cftime.DatetimeGregorian? If so, can the calendar default on the base class cftime.dateime be reverted to ''. In this case, dayofwk, etc. would be None (say) when called on the base class. Is there a use case for having the default as 'standard'?

Apologies for realizing these questions when these changes were being discussed - I have just found out when my units tests failed with 1.1.3!
Thanks, David

@jswhit
Copy link
Collaborator

jswhit commented May 18, 2020

I'm confused - you reported the bug that led to this change. Now it seems you are advocating a return to the state that triggered the bug?

cftime.DatetimeGregorian instantiates cftime.datetime with calendar='gregorian' (which is the same thing as 'standard'). It looks to me that the calendar attribute is only used by the dayofwk and dayofyr properties. As you point out, setting calendar='' will cause those properties, or anything that uses them, to raise an exception. It doesn't make sense to me to have a datetime instance without a calendar.

@davidhassell
Copy link
Contributor Author

Hi - Sorry to be confusing! What I wish I'd said is

"Can we further modify dayofwk to return -1 if calendar has been (legally) set to ''. The new default value of 'standard' is fine."

This would look like:

>>> d = cftime.datetime(2000, 1, 1)
>>> d.dayofwk
5
>>> e = cftime.datetime(2000, 1, 1, calendar='')
>>> e.dayofwk
-1                  

I am happy to create a PR for this, if everyone thinks that it is OK.

The use case for this is that retaining the ability to not set a calendar on cftime.datetime objects is very useful. This is so that calendar-agnostic date-times can be stored for evaluation in various, as yet unknown calendar contexts. For example, I would like to store the date-time 2000-01-01 so that later in my workflow I can test where my netCDF time coordinates from models with a range of calendars are later than this date.

Whilst setting calendar='' is allowed at initialization, downstream methods that need to calculate the day of the week will currently fail. These include dayofwk, dayofyr and timetuple. In particular, timetuple is useful for getting at the year, month, day, etc. so that a new version of the date-time in the calendar of the moment can be created.

Thanks for your patience,
David

@davidhassell
Copy link
Contributor Author

Hello - I have just discovered that the calendar reverts to 'standard' in the output of cftime.datetime.replace:

In [19]: d = cftime.datetime(2000, 1, 1, calendar='')

In [20]: e = d.replace(year=1999)

In [21]: e.calendar
Out[21]: 'standard'

In [22]: e = d.replace(year=1999, calendar='')

In [23]: e.calendar
Out[23]: ''

I'm happy to suggest a fix, if you like, to preserve the input calendar for the output, unless it has been set with a kwarg.

Thanks,
David

@jswhit
Copy link
Collaborator

jswhit commented May 19, 2020

OK, I understand better now. Please go ahead and submit a PR.

jswhit added a commit that referenced this issue May 29, 2020
Return the default values of dayofwk and dayofyr when calendar is '' (issue #173)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants