220 lines
5.7 KiB
Python
220 lines
5.7 KiB
Python
import re
|
|
|
|
import pytest
|
|
|
|
from pandas._libs.tslibs import (
|
|
Timedelta,
|
|
offsets,
|
|
to_offset,
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"freq_input,expected",
|
|
[
|
|
(to_offset("10us"), offsets.Micro(10)),
|
|
(offsets.Hour(), offsets.Hour()),
|
|
("2h30min", offsets.Minute(150)),
|
|
("2h 30min", offsets.Minute(150)),
|
|
("2h30min15s", offsets.Second(150 * 60 + 15)),
|
|
("2h 60min", offsets.Hour(3)),
|
|
("2h 20.5min", offsets.Second(8430)),
|
|
("1.5min", offsets.Second(90)),
|
|
("0.5s", offsets.Milli(500)),
|
|
("15ms500us", offsets.Micro(15500)),
|
|
("10s75ms", offsets.Milli(10075)),
|
|
("1s0.25ms", offsets.Micro(1000250)),
|
|
("1s0.25ms", offsets.Micro(1000250)),
|
|
("2800ns", offsets.Nano(2800)),
|
|
("2SME", offsets.SemiMonthEnd(2)),
|
|
("2SME-16", offsets.SemiMonthEnd(2, day_of_month=16)),
|
|
("2SMS-14", offsets.SemiMonthBegin(2, day_of_month=14)),
|
|
("2SMS-15", offsets.SemiMonthBegin(2)),
|
|
],
|
|
)
|
|
def test_to_offset(freq_input, expected):
|
|
result = to_offset(freq_input)
|
|
assert result == expected
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"freqstr,expected", [("-1s", -1), ("-2SME", -2), ("-1SMS", -1), ("-5min10s", -310)]
|
|
)
|
|
def test_to_offset_negative(freqstr, expected):
|
|
result = to_offset(freqstr)
|
|
assert result.n == expected
|
|
|
|
|
|
@pytest.mark.filterwarnings("ignore:.*'m' is deprecated.*:FutureWarning")
|
|
@pytest.mark.parametrize(
|
|
"freqstr",
|
|
[
|
|
"2h20m",
|
|
"us1",
|
|
"-us",
|
|
"3us1",
|
|
"-2-3us",
|
|
"-2D:3h",
|
|
"1.5.0s",
|
|
"2SMS-15-15",
|
|
"2SMS-15D",
|
|
"100foo",
|
|
# Invalid leading +/- signs.
|
|
"+-1d",
|
|
"-+1h",
|
|
"+1",
|
|
"-7",
|
|
"+d",
|
|
"-m",
|
|
# Invalid shortcut anchors.
|
|
"SME-0",
|
|
"SME-28",
|
|
"SME-29",
|
|
"SME-FOO",
|
|
"BSM",
|
|
"SME--1",
|
|
"SMS-1",
|
|
"SMS-28",
|
|
"SMS-30",
|
|
"SMS-BAR",
|
|
"SMS-BYR",
|
|
"BSMS",
|
|
"SMS--2",
|
|
],
|
|
)
|
|
def test_to_offset_invalid(freqstr):
|
|
# see gh-13930
|
|
|
|
# We escape string because some of our
|
|
# inputs contain regex special characters.
|
|
msg = re.escape(f"Invalid frequency: {freqstr}")
|
|
with pytest.raises(ValueError, match=msg):
|
|
to_offset(freqstr)
|
|
|
|
|
|
def test_to_offset_no_evaluate():
|
|
msg = str(("", ""))
|
|
with pytest.raises(TypeError, match=msg):
|
|
to_offset(("", ""))
|
|
|
|
|
|
def test_to_offset_tuple_unsupported():
|
|
with pytest.raises(TypeError, match="pass as a string instead"):
|
|
to_offset((5, "T"))
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"freqstr,expected",
|
|
[
|
|
("2D 3h", offsets.Hour(51)),
|
|
("2 D3 h", offsets.Hour(51)),
|
|
("2 D 3 h", offsets.Hour(51)),
|
|
(" 2 D 3 h ", offsets.Hour(51)),
|
|
(" h ", offsets.Hour()),
|
|
(" 3 h ", offsets.Hour(3)),
|
|
],
|
|
)
|
|
def test_to_offset_whitespace(freqstr, expected):
|
|
result = to_offset(freqstr)
|
|
assert result == expected
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"freqstr,expected", [("00h 00min 01s", 1), ("-00h 03min 14s", -194)]
|
|
)
|
|
def test_to_offset_leading_zero(freqstr, expected):
|
|
result = to_offset(freqstr)
|
|
assert result.n == expected
|
|
|
|
|
|
@pytest.mark.parametrize("freqstr,expected", [("+1d", 1), ("+2h30min", 150)])
|
|
def test_to_offset_leading_plus(freqstr, expected):
|
|
result = to_offset(freqstr)
|
|
assert result.n == expected
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"kwargs,expected",
|
|
[
|
|
({"days": 1, "seconds": 1}, offsets.Second(86401)),
|
|
({"days": -1, "seconds": 1}, offsets.Second(-86399)),
|
|
({"hours": 1, "minutes": 10}, offsets.Minute(70)),
|
|
({"hours": 1, "minutes": -10}, offsets.Minute(50)),
|
|
({"weeks": 1}, offsets.Day(7)),
|
|
({"hours": 1}, offsets.Hour(1)),
|
|
({"hours": 1}, to_offset("60min")),
|
|
({"microseconds": 1}, offsets.Micro(1)),
|
|
({"microseconds": 0}, offsets.Nano(0)),
|
|
],
|
|
)
|
|
def test_to_offset_pd_timedelta(kwargs, expected):
|
|
# see gh-9064
|
|
td = Timedelta(**kwargs)
|
|
result = to_offset(td)
|
|
assert result == expected
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"shortcut,expected",
|
|
[
|
|
("W", offsets.Week(weekday=6)),
|
|
("W-SUN", offsets.Week(weekday=6)),
|
|
("QE", offsets.QuarterEnd(startingMonth=12)),
|
|
("QE-DEC", offsets.QuarterEnd(startingMonth=12)),
|
|
("QE-MAY", offsets.QuarterEnd(startingMonth=5)),
|
|
("SME", offsets.SemiMonthEnd(day_of_month=15)),
|
|
("SME-15", offsets.SemiMonthEnd(day_of_month=15)),
|
|
("SME-1", offsets.SemiMonthEnd(day_of_month=1)),
|
|
("SME-27", offsets.SemiMonthEnd(day_of_month=27)),
|
|
("SMS-2", offsets.SemiMonthBegin(day_of_month=2)),
|
|
("SMS-27", offsets.SemiMonthBegin(day_of_month=27)),
|
|
],
|
|
)
|
|
def test_anchored_shortcuts(shortcut, expected):
|
|
result = to_offset(shortcut)
|
|
assert result == expected
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"freq_depr",
|
|
[
|
|
"2ye-mar",
|
|
"2ys",
|
|
"2qe",
|
|
"2qs-feb",
|
|
"2bqs",
|
|
"2sms",
|
|
"2bms",
|
|
"2cbme",
|
|
"2me",
|
|
"2w",
|
|
],
|
|
)
|
|
def test_to_offset_lowercase_frequency_deprecated(freq_depr):
|
|
# GH#54939
|
|
depr_msg = f"'{freq_depr[1:]}' is deprecated and will be removed in a "
|
|
f"future version, please use '{freq_depr.upper()[1:]}' instead."
|
|
|
|
with pytest.raises(FutureWarning, match=depr_msg):
|
|
to_offset(freq_depr)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"freq_depr",
|
|
[
|
|
"2H",
|
|
"2BH",
|
|
"2MIN",
|
|
"2S",
|
|
"2Us",
|
|
"2NS",
|
|
],
|
|
)
|
|
def test_to_offset_uppercase_frequency_deprecated(freq_depr):
|
|
# GH#54939
|
|
depr_msg = f"'{freq_depr[1:]}' is deprecated and will be removed in a "
|
|
f"future version, please use '{freq_depr.lower()[1:]}' instead."
|
|
|
|
with pytest.raises(FutureWarning, match=depr_msg):
|
|
to_offset(freq_depr)
|