-
-
Notifications
You must be signed in to change notification settings - Fork 18.5k
ENH: implement Timedelta._as_unit #47162
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 all commits
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 |
---|---|---|
|
@@ -13,6 +13,7 @@ | |
NaT, | ||
iNaT, | ||
) | ||
from pandas.errors import OutOfBoundsTimedelta | ||
|
||
import pandas as pd | ||
from pandas import ( | ||
|
@@ -24,6 +25,80 @@ | |
import pandas._testing as tm | ||
|
||
|
||
class TestAsUnit: | ||
def test_as_unit(self): | ||
td = Timedelta(days=1) | ||
|
||
assert td._as_unit("ns") is td | ||
|
||
res = td._as_unit("us") | ||
assert res.value == td.value // 1000 | ||
assert res._reso == td._reso - 1 | ||
|
||
rt = res._as_unit("ns") | ||
assert rt.value == td.value | ||
assert rt._reso == td._reso | ||
|
||
res = td._as_unit("ms") | ||
assert res.value == td.value // 1_000_000 | ||
assert res._reso == td._reso - 2 | ||
|
||
rt = res._as_unit("ns") | ||
assert rt.value == td.value | ||
assert rt._reso == td._reso | ||
|
||
res = td._as_unit("s") | ||
assert res.value == td.value // 1_000_000_000 | ||
assert res._reso == td._reso - 3 | ||
|
||
rt = res._as_unit("ns") | ||
assert rt.value == td.value | ||
assert rt._reso == td._reso | ||
|
||
def test_as_unit_overflows(self): | ||
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. Just confirming aloud, based on the multiplication operation we can't get to a state where underflowing occurs (and therefore can't test that)? 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 is all in integers, so i dont think underflows are an issue |
||
# microsecond that would be just out of bounds for nano | ||
us = 9223372800000000 | ||
td = Timedelta._from_value_and_reso(us, 9) | ||
|
||
msg = "Cannot cast 106752 days 00:00:00 to unit='ns' without overflow" | ||
with pytest.raises(OutOfBoundsTimedelta, match=msg): | ||
td._as_unit("ns") | ||
|
||
res = td._as_unit("ms") | ||
assert res.value == us // 1000 | ||
assert res._reso == 8 | ||
|
||
def test_as_unit_rounding(self): | ||
td = Timedelta(microseconds=1500) | ||
res = td._as_unit("ms") | ||
|
||
expected = Timedelta(milliseconds=1) | ||
assert res == expected | ||
|
||
assert res._reso == 8 | ||
assert res.value == 1 | ||
|
||
with pytest.raises(ValueError, match="Cannot losslessly convert units"): | ||
td._as_unit("ms", round_ok=False) | ||
|
||
def test_as_unit_non_nano(self): | ||
# case where we are going neither to nor from nano | ||
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 what 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 to nano" and "not from nano" |
||
td = Timedelta(days=1)._as_unit("D") | ||
assert td.days == 1 | ||
assert td.value == 1 | ||
assert td.components.days == 1 | ||
assert td._d == 1 | ||
assert td.total_seconds() == 86400 | ||
|
||
res = td._as_unit("h") | ||
assert res.value == 24 | ||
assert res.components.days == 1 | ||
assert res.components.hours == 0 | ||
assert res._d == 1 | ||
assert res._h == 0 | ||
assert res.total_seconds() == 86400 | ||
|
||
|
||
class TestNonNano: | ||
@pytest.fixture(params=[7, 8, 9]) | ||
def unit(self, request): | ||
|
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.
Did this fix a bug somewhere?
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.
turns out not to be relevant, could actually get rid of per_day here entirely