You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

220 lines
5.7 KiB

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)