Skip to content

ENH: Implement round dunder methods for Timestamp and Timedelta #58081

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

Closed
wants to merge 4 commits into from

Conversation

Aloqeely
Copy link
Member

@Aloqeely Aloqeely requested a review from MarcoGorelli as a code owner March 29, 2024 22:02
@Aloqeely
Copy link
Member Author

pre-commit.ci autofix

@@ -2290,6 +2290,9 @@ class Timedelta(_Timedelta):
div = other // self
return div, other - div * self

def __round__(self, freq):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn’t the dunder method not take a freq keyword?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right it doesn't, it instead takes ndigits which is not relevant here, so I thought for extra customizability I'll take freq in place of ndigits (same as NDFrame.__round__ which takes decimals instead of ndigits)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I have 1 question, should freq have a default value? as you would usually expect round(object) to work without any extra arguments, if so, what should the default value be?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not expect that to work

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weirdly enough it does, for example:

In [1]: import pandas as pd
In [2]: td = pd.Timedelta(days=1, hours=2, minutes=34, seconds=56.78)
In [3]: round(td, "s")
Out[3]: Timedelta('1 days 02:34:57')
In [4]: round(td)
TypeError: __round__() takes exactly 2 positional arguments (1 given)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or were you replying to my last sentence when I said that I expect round(object) to work without any args

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or were you replying to my last sentence when I said that I expect round(object) to work without any args

That

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this just happens to work due to an implementation detail in CPython, then it seems to me to be an abuse of the Python API and could break in the future. Is supporting other arguments in Python's round documented somewhere?

Copy link
Contributor

@asishm asishm Mar 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

python round which is just object.__round__(self[, ndigits])

Copy link
Member

@mroeschke mroeschke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think __round__ should be implemented for these objects. Since round is only well specified for numeric values, I think it's too opaque to apply for datelike objects.

@Aloqeely
Copy link
Member Author

Aloqeely commented Apr 1, 2024

Makes sense, I apologize, I was too hasty to make a PR.
Should I close this and wait until a decision is made?

@mroeschke
Copy link
Member

I would recommend closing this PR until discussion in the issue has resolved

@Aloqeely Aloqeely closed this Apr 1, 2024
@JustAnotherVeryNormalDeveloper
Copy link

JustAnotherVeryNormalDeveloper commented Apr 5, 2024

I don't think __round__ should be implemented for these objects. Since round is only well specified for numeric values, I think it's too opaque to apply for datelike objects.

@mroeschke @MarcoGorelli @rhshadrach

Hello, I was the one that created the issue.

There is already an implementation of a round method for timedelta

pd.Timedelta.round('s') works. (https://pandas.pydata.org/docs/reference/api/pandas.Timedelta.round.html)
so round(pd.Timedelta) feel intuitive and just need to be added ?

(I'm going on again because I still use the fix I made here #58071 on my production server and I would be happy to not have to handle this manually but to see the library handle it).

@rhshadrach
Copy link
Member

rhshadrach commented Apr 5, 2024

so round(pd.Timedelta) feel intuitive and just need to be added ?

As commented above (#58081 (comment)):

If this just happens to work due to an implementation detail in CPython, then it seems to me to be an abuse of the Python API and could break in the future.

Do you disagree that making round(pd.Timedelta) work as it's implemented in this PR is an abuse of the Python API?

Alternatively, if you are wanting the signature to be something like def __round__(self, n=None): and have the n mean seconds, then I am still of the opinion expressed in #58071 (comment) and quite negative on adding this.

@JustAnotherVeryNormalDeveloper
Copy link

JustAnotherVeryNormalDeveloper commented Apr 8, 2024

So because round(td, n=5) isn't really clear, you don't want to implement round(td).
I understand your point of view.

I disagree that it's a good enough reason to not do it.
with or without this feature, round(td, n=5) would crash.
by doing this feature, hundreds/thousand of developers throughs ages would feel the library even more intuitive with round(td).
But the philosophical defense is understandable. It feels like the defense of a C++ dev rather than python dev but I understand.

Have a nice day boys and thanks for this library (I use it every day at work and I love it !<3)

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

Successfully merging this pull request may close these issues.

BUG: TypeError("type Timedelta doesn't define __round__ method")
6 participants