-
-
Notifications
You must be signed in to change notification settings - Fork 18.4k
Split+Parametrize Timedelta tests #19736
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 6 commits
f36d8e1
1a4b7c7
27b7c05
ecb698b
dafae93
d1d0b22
2301db5
4829920
a852a4b
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 |
---|---|---|
@@ -0,0 +1,217 @@ | ||
# -*- coding: utf-8 -*- | ||
from datetime import timedelta | ||
|
||
import pytest | ||
import numpy as np | ||
|
||
import pandas as pd | ||
import pandas.util.testing as tm | ||
from pandas import Timedelta | ||
|
||
|
||
class TestTimedeltaConstructor(object): | ||
def test_construction(self): | ||
expected = np.timedelta64(10, 'D').astype('m8[ns]').view('i8') | ||
assert Timedelta(10, unit='d').value == expected | ||
assert Timedelta(10.0, unit='d').value == expected | ||
assert Timedelta('10 days').value == expected | ||
assert Timedelta(days=10).value == expected | ||
assert Timedelta(days=10.0).value == expected | ||
|
||
expected += np.timedelta64(10, 's').astype('m8[ns]').view('i8') | ||
assert Timedelta('10 days 00:00:10').value == expected | ||
assert Timedelta(days=10, seconds=10).value == expected | ||
assert Timedelta(days=10, milliseconds=10 * 1000).value == expected | ||
assert Timedelta(days=10, | ||
microseconds=10 * 1000 * 1000).value == expected | ||
|
||
# rounding cases | ||
assert Timedelta(82739999850000).value == 82739999850000 | ||
assert ('0 days 22:58:59.999850' in str(Timedelta(82739999850000))) | ||
assert Timedelta(123072001000000).value == 123072001000000 | ||
assert ('1 days 10:11:12.001' in str(Timedelta(123072001000000))) | ||
|
||
# string conversion with/without leading zero | ||
# GH#9570 | ||
assert Timedelta('0:00:00') == timedelta(hours=0) | ||
assert Timedelta('00:00:00') == timedelta(hours=0) | ||
assert Timedelta('-1:00:00') == -timedelta(hours=1) | ||
assert Timedelta('-01:00:00') == -timedelta(hours=1) | ||
|
||
# more strings & abbrevs | ||
# GH#8190 | ||
assert Timedelta('1 h') == timedelta(hours=1) | ||
assert Timedelta('1 hour') == timedelta(hours=1) | ||
assert Timedelta('1 hr') == timedelta(hours=1) | ||
assert Timedelta('1 hours') == timedelta(hours=1) | ||
assert Timedelta('-1 hours') == -timedelta(hours=1) | ||
assert Timedelta('1 m') == timedelta(minutes=1) | ||
assert Timedelta('1.5 m') == timedelta(seconds=90) | ||
assert Timedelta('1 minute') == timedelta(minutes=1) | ||
assert Timedelta('1 minutes') == timedelta(minutes=1) | ||
assert Timedelta('1 s') == timedelta(seconds=1) | ||
assert Timedelta('1 second') == timedelta(seconds=1) | ||
assert Timedelta('1 seconds') == timedelta(seconds=1) | ||
assert Timedelta('1 ms') == timedelta(milliseconds=1) | ||
assert Timedelta('1 milli') == timedelta(milliseconds=1) | ||
assert Timedelta('1 millisecond') == timedelta(milliseconds=1) | ||
assert Timedelta('1 us') == timedelta(microseconds=1) | ||
assert Timedelta('1 micros') == timedelta(microseconds=1) | ||
assert Timedelta('1 microsecond') == timedelta(microseconds=1) | ||
assert Timedelta('1.5 microsecond') == Timedelta('00:00:00.000001500') | ||
assert Timedelta('1 ns') == Timedelta('00:00:00.000000001') | ||
assert Timedelta('1 nano') == Timedelta('00:00:00.000000001') | ||
assert Timedelta('1 nanosecond') == Timedelta('00:00:00.000000001') | ||
|
||
# combos | ||
assert Timedelta('10 days 1 hour') == timedelta(days=10, hours=1) | ||
assert Timedelta('10 days 1 h') == timedelta(days=10, hours=1) | ||
assert Timedelta('10 days 1 h 1m 1s') == timedelta( | ||
days=10, hours=1, minutes=1, seconds=1) | ||
assert Timedelta('-10 days 1 h 1m 1s') == -timedelta( | ||
days=10, hours=1, minutes=1, seconds=1) | ||
assert Timedelta('-10 days 1 h 1m 1s') == -timedelta( | ||
days=10, hours=1, minutes=1, seconds=1) | ||
assert Timedelta('-10 days 1 h 1m 1s 3us') == -timedelta( | ||
days=10, hours=1, minutes=1, seconds=1, microseconds=3) | ||
assert Timedelta('-10 days 1 h 1.5m 1s 3us') == -timedelta( | ||
days=10, hours=1, minutes=1, seconds=31, microseconds=3) | ||
|
||
# Currently invalid as it has a - on the hh:mm:dd part | ||
# (only allowed on the days) | ||
with pytest.raises(ValueError): | ||
Timedelta('-10 days -1 h 1.5m 1s 3us') | ||
|
||
# only leading neg signs are allowed | ||
with pytest.raises(ValueError): | ||
Timedelta('10 days -1 h 1.5m 1s 3us') | ||
|
||
# no units specified | ||
with pytest.raises(ValueError): | ||
Timedelta('3.1415') | ||
|
||
# invalid construction | ||
tm.assert_raises_regex(ValueError, "cannot construct a Timedelta", | ||
lambda: Timedelta()) | ||
tm.assert_raises_regex(ValueError, | ||
"unit abbreviation w/o a number", | ||
lambda: Timedelta('foo')) | ||
tm.assert_raises_regex(ValueError, | ||
"cannot construct a Timedelta from the " | ||
"passed arguments, allowed keywords are ", | ||
lambda: Timedelta(day=10)) | ||
|
||
# floats | ||
expected = np.timedelta64( | ||
10, 's').astype('m8[ns]').view('i8') + np.timedelta64( | ||
500, 'ms').astype('m8[ns]').view('i8') | ||
assert Timedelta(10.5, unit='s').value == expected | ||
|
||
# offset | ||
assert pd.to_timedelta(pd.offsets.Hour(2)) == Timedelta(hours=2) | ||
assert Timedelta(pd.offsets.Hour(2)) == Timedelta(hours=2) | ||
assert Timedelta(pd.offsets.Second(2)) == Timedelta(seconds=2) | ||
|
||
# GH#11995: unicode | ||
expected = Timedelta('1H') | ||
result = pd.Timedelta(u'1H') | ||
assert result == expected | ||
assert (pd.to_timedelta(pd.offsets.Hour(2)) == | ||
Timedelta(u'0 days, 02:00:00')) | ||
|
||
with pytest.raises(ValueError): | ||
Timedelta(u'foo bar') | ||
|
||
@pytest.mark.parametrize('item', list({'days': 'D', | ||
'seconds': 's', | ||
'microseconds': 'us', | ||
'milliseconds': 'ms', | ||
'minutes': 'm', | ||
'hours': 'h', | ||
'weeks': 'W'}.items())) | ||
@pytest.mark.parametrize('npdtype', [np.int64, np.int32, np.int16, | ||
np.float64, np.float32, np.float16]) | ||
def test_td_construction_with_np_dtypes(self, npdtype, item): | ||
# GH#8757: test construction with np dtypes | ||
pykwarg, npkwarg = item | ||
expected = np.timedelta64(1, npkwarg).astype('m8[ns]').view('i8') | ||
assert Timedelta(**{pykwarg: npdtype(1)}).value == expected | ||
|
||
@pytest.mark.parametrize('val', [ | ||
'1s', '-1s', '1us', '-1us', '1 day', '-1 day', | ||
'-23:59:59.999999', '-1 days +23:59:59.999999', '-1ns', | ||
'1ns', '-23:59:59.999999999']) | ||
def test_td_from_repr_roundtrip(self, val): | ||
# round-trip both for string and value | ||
td = Timedelta(val) | ||
assert Timedelta(td.value) == td | ||
|
||
# str does not normally display nanos | ||
if not td.nanoseconds: | ||
assert Timedelta(str(td)) == td | ||
assert Timedelta(td._repr_base(format='all')) == td | ||
|
||
def test_overflow_on_construction(self): | ||
# xref https://github.com/statsmodels/statsmodels/issues/3374 | ||
value = pd.Timedelta('1day').value * 20169940 | ||
with pytest.raises(OverflowError): | ||
pd.Timedelta(value) | ||
|
||
# xref GH#17637 | ||
with pytest.raises(OverflowError): | ||
pd.Timedelta(7 * 19999, unit='D') | ||
|
||
with pytest.raises(OverflowError): | ||
pd.Timedelta(timedelta(days=13 * 19999)) | ||
|
||
@pytest.mark.parametrize('fmt,exp', [ | ||
('P6DT0H50M3.010010012S', Timedelta(days=6, minutes=50, seconds=3, | ||
milliseconds=10, microseconds=10, | ||
nanoseconds=12)), | ||
('P-6DT0H50M3.010010012S', Timedelta(days=-6, minutes=50, seconds=3, | ||
milliseconds=10, microseconds=10, | ||
nanoseconds=12)), | ||
('P4DT12H30M5S', Timedelta(days=4, hours=12, minutes=30, seconds=5)), | ||
('P0DT0H0M0.000000123S', Timedelta(nanoseconds=123)), | ||
('P0DT0H0M0.00001S', Timedelta(microseconds=10)), | ||
('P0DT0H0M0.001S', Timedelta(milliseconds=1)), | ||
('P0DT0H1M0S', Timedelta(minutes=1)), | ||
('P1DT25H61M61S', Timedelta(days=1, hours=25, minutes=61, seconds=61)) | ||
]) | ||
def test_iso_constructor(self, fmt, exp): | ||
assert Timedelta(fmt) == exp | ||
|
||
@pytest.mark.parametrize('fmt', [ | ||
'PPPPPPPPPPPP', 'PDTHMS', 'P0DT999H999M999S', | ||
'P1DT0H0M0.0000000000000S', 'P1DT0H0M00000000000S', | ||
'P1DT0H0M0.S']) | ||
def test_iso_constructor_raises(self, fmt): | ||
with tm.assert_raises_regex(ValueError, 'Invalid ISO 8601 Duration ' | ||
'format - {}'.format(fmt)): | ||
Timedelta(fmt) | ||
|
||
def test_td_constructor_on_nanoseconds(self): | ||
# GH#9273 | ||
result = Timedelta(nanoseconds=100) | ||
expected = Timedelta('100ns') | ||
assert result == expected | ||
|
||
result = Timedelta(days=1, hours=1, minutes=1, weeks=1, seconds=1, | ||
milliseconds=1, microseconds=1, nanoseconds=1) | ||
expected = Timedelta(694861001001001) | ||
assert result == expected | ||
|
||
result = Timedelta(microseconds=1) + Timedelta(nanoseconds=1) | ||
expected = Timedelta('1us1ns') | ||
assert result == expected | ||
|
||
result = Timedelta(microseconds=1) - Timedelta(nanoseconds=1) | ||
expected = Timedelta('999ns') | ||
assert result == expected | ||
|
||
result = Timedelta(microseconds=1) + 5 * Timedelta(nanoseconds=-2) | ||
expected = Timedelta('990ns') | ||
assert result == expected | ||
|
||
with pytest.raises(TypeError): | ||
Timedelta(nanoseconds='abc') |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# -*- coding: utf-8 -*- | ||
from pandas import Timedelta | ||
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. can you de-class these. I think we are calling this test_formats.py elsewhere? 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.
In scalar.timestamps we're calling it test_rendering. In tests.indexes we recently moved a bunch of thematically related tests to pre-existing test_formats.py files (that each only had one test in them, so seemed lonely). I have a mild preference for "test_rendering" since it is pretty specifically about 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 use test_formats for now. |
||
|
||
|
||
class TestTimedeltaRendering(object): | ||
def test_repr(self): | ||
assert (repr(Timedelta(10, unit='d')) == | ||
"Timedelta('10 days 00:00:00')") | ||
assert (repr(Timedelta(10, unit='s')) == | ||
"Timedelta('0 days 00:00:10')") | ||
assert (repr(Timedelta(10, unit='ms')) == | ||
"Timedelta('0 days 00:00:00.010000')") | ||
assert (repr(Timedelta(-10, unit='ms')) == | ||
"Timedelta('-1 days +23:59:59.990000')") | ||
|
||
def test_isoformat(self): | ||
td = Timedelta(days=6, minutes=50, seconds=3, | ||
milliseconds=10, microseconds=10, nanoseconds=12) | ||
expected = 'P6DT0H50M3.010010012S' | ||
result = td.isoformat() | ||
assert result == expected | ||
|
||
td = Timedelta(days=4, hours=12, minutes=30, seconds=5) | ||
result = td.isoformat() | ||
expected = 'P4DT12H30M5S' | ||
assert result == expected | ||
|
||
td = Timedelta(nanoseconds=123) | ||
result = td.isoformat() | ||
expected = 'P0DT0H0M0.000000123S' | ||
assert result == expected | ||
|
||
# trim nano | ||
td = Timedelta(microseconds=10) | ||
result = td.isoformat() | ||
expected = 'P0DT0H0M0.00001S' | ||
assert result == expected | ||
|
||
# trim micro | ||
td = Timedelta(milliseconds=1) | ||
result = td.isoformat() | ||
expected = 'P0DT0H0M0.001S' | ||
assert result == expected | ||
|
||
# don't strip every 0 | ||
result = Timedelta(minutes=1).isoformat() | ||
expected = 'P0DT0H1M0S' | ||
assert result == expected |
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.
can you de-class these
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.
Sure.