-
-
Notifications
You must be signed in to change notification settings - Fork 18.7k
BUG: Fix nanosecond timedeltas #45108
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
Changes from 4 commits
cff6ee6
c0f8127
c9d7747
e1110bf
4406deb
b8d37e7
88145b5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -236,6 +236,8 @@ Other enhancements | |||||
- :meth:`is_list_like` now identifies duck-arrays as list-like unless ``.ndim == 0`` (:issue:`35131`) | ||||||
- :class:`ExtensionDtype` and :class:`ExtensionArray` are now (de)serialized when exporting a :class:`DataFrame` with :meth:`DataFrame.to_json` using ``orient='table'`` (:issue:`20612`, :issue:`44705`). | ||||||
- Add support for `Zstandard <http://facebook.github.io/zstd/>`_ compression to :meth:`DataFrame.to_pickle`/:meth:`read_pickle` and friends (:issue:`43925`) | ||||||
- :class:`Timedelta` now properly taking into account any nanoseconds contribution (:issue: `43764`) | ||||||
- :meth:`Timedelta.total_seconds()` now properly taking into account any nanoseconds contribution (:issue: `40946`) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||
- | ||||||
|
||||||
|
||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1268,7 +1268,16 @@ class Timedelta(_Timedelta): | |
|
||
kwargs = {key: _to_py_int_float(kwargs[key]) for key in kwargs} | ||
|
||
nano = convert_to_timedelta64(kwargs.pop('nanoseconds', 0), 'ns') | ||
# GH43764, making sure any nanoseconds contributions from any kwarg is taken into consideration | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. umm this is just duplicating code from below There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know exactly which code you're referring to, but if I do not catch all nanoseconds contributions when a |
||
nano = convert_to_timedelta64( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you are entirely duplicating L1283 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My modifications removed "microseconds" till "seconds" from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i actually don't have a problem with doing what you are doing but then you need to entirely remove L1282-1284 and handle all the kwargs (well you still need the try/except). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this will also slow this function down a lot. rather than poping be explicit on the argument handling There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you check the last changes? I profiled instantiation time and it is taking about 50% the time as in master.
|
||
( | ||
kwargs.pop('nanoseconds', 0) | ||
+ kwargs.pop('microseconds', 0) * 1000 | ||
+ kwargs.pop('milliseconds', 0) * 1000000 | ||
+ kwargs.pop('seconds', 0) * 1000000000 | ||
), 'ns' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. because these are floats, I assume that this will lose precision near the limits. i.e. seconds = 106751 (days) * 24*3600 with a nanosecond component specified too? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not really sure, but I would expect that when aiming at precision the inputs should instead be coded as integers by the caller? My motivation here is only to make the instantiation consistent in that, if float inputs are allowed, then any nanosecond contributions from any supplied There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. indeed, if any of these components is a float. so gives There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you check my last commit? It produces the same output as in |
||
) | ||
|
||
try: | ||
value = nano + convert_to_timedelta64(timedelta(**kwargs), | ||
'ns') | ||
|
@@ -1520,6 +1529,10 @@ class Timedelta(_Timedelta): | |
div = other // self | ||
return div, other - div * self | ||
|
||
# GH40946 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. doc string and types pls There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done on premise. (Depends on the decision to separate the issues in two PRs or not) |
||
def total_seconds(self): | ||
return self.value / 1e9 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. internally, ns precision is achieved by storing the value as a 64 bit integer. once this is converted to a float, we cannot maintain ns precision. However, including the nanosecond component is probably more accurate than ignoring it. I think we need more discussion on the issue before re-instating the nanosecond "precision". from #31380 (comment)
The change to ms precision was an intentional one but was not documented. Changing it back would probably require a specific mention in the release note. Also the tests are failing for the cases added when the precision of I also think that the 2 issue should be addressed independently. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Before I go and refactor/enhance the tests, it would be nice to have a categorical decision on this topic. Should the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
the two fixes are orthogonal? The override of the If so, I think should be two separate PRs. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes pls split to a sepearate PR |
||
|
||
|
||
cdef bint is_any_td_scalar(object obj): | ||
""" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.