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

DOC: undocumented behavior for converting month timedelta64 to days #26121

Closed
zazaho opened this issue Mar 23, 2024 · 4 comments · Fixed by #26322
Closed

DOC: undocumented behavior for converting month timedelta64 to days #26121

zazaho opened this issue Mar 23, 2024 · 4 comments · Fixed by #26322

Comments

@zazaho
Copy link

zazaho commented Mar 23, 2024

Issue with current documentation:

I have three syntaxes that attempt to convert a timedelta64 in month into days. As is well explained in the documentation:
https://numpy.org/doc/stable/reference/arrays.datetime.html#arrays-datetime
this is not possible because we do not know how many days a month holds:

np.timedelta64(1, 'M') / np.timedelta64(1, 'D')
Cannot get a common metadata divisor for Numpy datetime metadata [M] and [D] because they have incompatible nonlinear base time units.

timedelta64(timedelta64(1, 'M'), 'D')
Cannot cast NumPy timedelta64 scalar from metadata [M] to [D] according to the rule 'same_kind'

but this yields:

timedelta64(1, 'M').astype(timedelta64(1, 'D'))
numpy.timedelta64(30,'D')

I am surprised that there is no error in the latter case but I am mostly interested to find out which rules are used to determine 30 in this case. For example:

timedelta64(3, 'M').astype(timedelta64(1, 'D'))
numpy.timedelta64(91,'D')

which indicates to me that there is some kind of heuristics used but I have not been able to find its documentation.

Thank you for your help,

Sacha

Idea or request for content:

No response

@zazaho zazaho changed the title DOC: undocumented behavior for converting timedelta64 to days DOC: undocumented behavior for converting month timedelta64 to days Mar 23, 2024
@ngoldbaum
Copy link
Member

ngoldbaum commented Mar 25, 2024

I am surprised that there is no error in the latter case

This is happening because numpy defaults to "unsafe" casting in astype:

>>> np.timedelta64(1, 'M').astype(np.timedelta64(1, 'D'))
np.timedelta64(30,'D')
>>> np.timedelta64(1, 'M').astype(np.timedelta64(1, 'D'), casting='safe')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Cannot cast scalar from dtype('<m8[M]') to dtype('<m8[D]') according to the rule 'safe'

which indicates to me that there is some kind of heuristics used but I have not been able to find its documentation.

According to the source code, this is the correct result averaged over a 400 year leap-year cycle:

else {
/* Month -> Day */
num *= (97 + 400*365);
denom *= 400*12;

A PR documenting these rules would be very welcome.

@sharsha315
Copy link

Hi, is this issue still open. Please, can I have the opportunity to work on this issue.

@ngoldbaum
Copy link
Member

We don’t claim issues in numpy, please go ahead, in the future just check if anyone already has a PR open for an issue

@ajayjanapareddi
Copy link
Contributor

Hi @ngoldbaum ,
Could you kindly review my first PR on numpy. Apologies if there are any mistakes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants