8th day of python challenges 111-117

This commit is contained in:
abd.shallal
2019-08-04 15:26:35 +03:00
parent b04c1b055f
commit 627802c383
3215 changed files with 760227 additions and 491 deletions

View File

@@ -0,0 +1,192 @@
import pytest
from pandas._libs.tslibs import frequencies as libfrequencies, resolution
from pandas._libs.tslibs.frequencies import (
FreqGroup,
_period_code_map,
get_freq,
get_freq_code,
)
import pandas.tseries.offsets as offsets
@pytest.fixture(params=list(_period_code_map.items()))
def period_code_item(request):
return request.param
@pytest.mark.parametrize(
"freqstr,expected",
[
("A", 1000),
("3A", 1000),
("-1A", 1000),
("Y", 1000),
("3Y", 1000),
("-1Y", 1000),
("W", 4000),
("W-MON", 4001),
("W-FRI", 4005),
],
)
def test_freq_code(freqstr, expected):
assert get_freq(freqstr) == expected
def test_freq_code_match(period_code_item):
freqstr, code = period_code_item
assert get_freq(freqstr) == code
@pytest.mark.parametrize(
"freqstr,expected",
[
("A", 1000),
("3A", 1000),
("-1A", 1000),
("A-JAN", 1000),
("A-MAY", 1000),
("Y", 1000),
("3Y", 1000),
("-1Y", 1000),
("Y-JAN", 1000),
("Y-MAY", 1000),
(offsets.YearEnd(), 1000),
(offsets.YearEnd(month=1), 1000),
(offsets.YearEnd(month=5), 1000),
("W", 4000),
("W-MON", 4000),
("W-FRI", 4000),
(offsets.Week(), 4000),
(offsets.Week(weekday=1), 4000),
(offsets.Week(weekday=5), 4000),
("T", FreqGroup.FR_MIN),
],
)
def test_freq_group(freqstr, expected):
assert resolution.get_freq_group(freqstr) == expected
def test_freq_group_match(period_code_item):
freqstr, code = period_code_item
str_group = resolution.get_freq_group(freqstr)
code_group = resolution.get_freq_group(code)
assert str_group == code_group == code // 1000 * 1000
@pytest.mark.parametrize(
"freqstr,exp_freqstr",
[("D", "D"), ("W", "D"), ("M", "D"), ("S", "S"), ("T", "S"), ("H", "S")],
)
def test_get_to_timestamp_base(freqstr, exp_freqstr):
tsb = libfrequencies.get_to_timestamp_base
assert tsb(get_freq_code(freqstr)[0]) == get_freq_code(exp_freqstr)[0]
_reso = resolution.Resolution
@pytest.mark.parametrize(
"freqstr,expected",
[
("A", "year"),
("Q", "quarter"),
("M", "month"),
("D", "day"),
("H", "hour"),
("T", "minute"),
("S", "second"),
("L", "millisecond"),
("U", "microsecond"),
("N", "nanosecond"),
],
)
def test_get_str_from_freq(freqstr, expected):
assert _reso.get_str_from_freq(freqstr) == expected
@pytest.mark.parametrize("freq", ["A", "Q", "M", "D", "H", "T", "S", "L", "U", "N"])
def test_get_freq_roundtrip(freq):
result = _reso.get_freq(_reso.get_str_from_freq(freq))
assert freq == result
@pytest.mark.parametrize("freq", ["D", "H", "T", "S", "L", "U"])
def test_get_freq_roundtrip2(freq):
result = _reso.get_freq(_reso.get_str(_reso.get_reso_from_freq(freq)))
assert freq == result
@pytest.mark.parametrize(
"args,expected",
[
((1.5, "T"), (90, "S")),
((62.4, "T"), (3744, "S")),
((1.04, "H"), (3744, "S")),
((1, "D"), (1, "D")),
((0.342931, "H"), (1234551600, "U")),
((1.2345, "D"), (106660800, "L")),
],
)
def test_resolution_bumping(args, expected):
# see gh-14378
assert _reso.get_stride_from_decimal(*args) == expected
@pytest.mark.parametrize(
"args",
[
(0.5, "N"),
# Too much precision in the input can prevent.
(0.3429324798798269273987982, "H"),
],
)
def test_cat(args):
msg = "Could not convert to integer offset at any resolution"
with pytest.raises(ValueError, match=msg):
_reso.get_stride_from_decimal(*args)
@pytest.mark.parametrize(
"freq_input,expected",
[
# Frequency string.
("A", (get_freq("A"), 1)),
("3D", (get_freq("D"), 3)),
("-2M", (get_freq("M"), -2)),
# Tuple.
(("D", 1), (get_freq("D"), 1)),
(("A", 3), (get_freq("A"), 3)),
(("M", -2), (get_freq("M"), -2)),
((5, "T"), (FreqGroup.FR_MIN, 5)),
# Numeric Tuple.
((1000, 1), (1000, 1)),
# Offsets.
(offsets.Day(), (get_freq("D"), 1)),
(offsets.Day(3), (get_freq("D"), 3)),
(offsets.Day(-2), (get_freq("D"), -2)),
(offsets.MonthEnd(), (get_freq("M"), 1)),
(offsets.MonthEnd(3), (get_freq("M"), 3)),
(offsets.MonthEnd(-2), (get_freq("M"), -2)),
(offsets.Week(), (get_freq("W"), 1)),
(offsets.Week(3), (get_freq("W"), 3)),
(offsets.Week(-2), (get_freq("W"), -2)),
(offsets.Hour(), (FreqGroup.FR_HR, 1)),
# Monday is weekday=0.
(offsets.Week(weekday=1), (get_freq("W-TUE"), 1)),
(offsets.Week(3, weekday=0), (get_freq("W-MON"), 3)),
(offsets.Week(-2, weekday=4), (get_freq("W-FRI"), -2)),
],
)
def test_get_freq_code(freq_input, expected):
assert get_freq_code(freq_input) == expected
def test_get_code_invalid():
with pytest.raises(ValueError, match="Invalid frequency"):
get_freq_code((5, "baz"))

View File

@@ -0,0 +1,535 @@
from datetime import datetime, timedelta
import numpy as np
import pytest
from pandas._libs.tslibs.ccalendar import DAYS, MONTHS
from pandas._libs.tslibs.frequencies import INVALID_FREQ_ERR_MSG
from pandas.compat import is_platform_windows
from pandas import DatetimeIndex, Index, Series, Timestamp, date_range, period_range
from pandas.core.tools.datetimes import to_datetime
import pandas.util.testing as tm
import pandas.tseries.frequencies as frequencies
import pandas.tseries.offsets as offsets
def _check_generated_range(start, periods, freq):
"""
Check the range generated from a given start, frequency, and period count.
Parameters
----------
start : str
The start date.
periods : int
The number of periods.
freq : str
The frequency of the range.
"""
freq = freq.upper()
gen = date_range(start, periods=periods, freq=freq)
index = DatetimeIndex(gen.values)
if not freq.startswith("Q-"):
assert frequencies.infer_freq(index) == gen.freqstr
else:
inf_freq = frequencies.infer_freq(index)
is_dec_range = inf_freq == "Q-DEC" and gen.freqstr in (
"Q",
"Q-DEC",
"Q-SEP",
"Q-JUN",
"Q-MAR",
)
is_nov_range = inf_freq == "Q-NOV" and gen.freqstr in (
"Q-NOV",
"Q-AUG",
"Q-MAY",
"Q-FEB",
)
is_oct_range = inf_freq == "Q-OCT" and gen.freqstr in (
"Q-OCT",
"Q-JUL",
"Q-APR",
"Q-JAN",
)
assert is_dec_range or is_nov_range or is_oct_range
@pytest.fixture(
params=[
(timedelta(1), "D"),
(timedelta(hours=1), "H"),
(timedelta(minutes=1), "T"),
(timedelta(seconds=1), "S"),
(np.timedelta64(1, "ns"), "N"),
(timedelta(microseconds=1), "U"),
(timedelta(microseconds=1000), "L"),
]
)
def base_delta_code_pair(request):
return request.param
@pytest.fixture(params=[1, 2, 3, 4])
def count(request):
return request.param
@pytest.fixture(params=DAYS)
def day(request):
return request.param
@pytest.fixture(params=MONTHS)
def month(request):
return request.param
@pytest.fixture(params=[5, 7])
def periods(request):
return request.param
def test_raise_if_period_index():
index = period_range(start="1/1/1990", periods=20, freq="M")
msg = "Check the `freq` attribute instead of using infer_freq"
with pytest.raises(TypeError, match=msg):
frequencies.infer_freq(index)
def test_raise_if_too_few():
index = DatetimeIndex(["12/31/1998", "1/3/1999"])
msg = "Need at least 3 dates to infer frequency"
with pytest.raises(ValueError, match=msg):
frequencies.infer_freq(index)
def test_business_daily():
index = DatetimeIndex(["01/01/1999", "1/4/1999", "1/5/1999"])
assert frequencies.infer_freq(index) == "B"
def test_business_daily_look_alike():
# see gh-16624
#
# Do not infer "B when "weekend" (2-day gap) in wrong place.
index = DatetimeIndex(["12/31/1998", "1/3/1999", "1/4/1999"])
assert frequencies.infer_freq(index) is None
def test_day_corner():
index = DatetimeIndex(["1/1/2000", "1/2/2000", "1/3/2000"])
assert frequencies.infer_freq(index) == "D"
def test_non_datetime_index():
dates = to_datetime(["1/1/2000", "1/2/2000", "1/3/2000"])
assert frequencies.infer_freq(dates) == "D"
def test_fifth_week_of_month_infer():
# see gh-9425
#
# Only attempt to infer up to WOM-4.
index = DatetimeIndex(["2014-03-31", "2014-06-30", "2015-03-30"])
assert frequencies.infer_freq(index) is None
def test_week_of_month_fake():
# All of these dates are on same day
# of week and are 4 or 5 weeks apart.
index = DatetimeIndex(["2013-08-27", "2013-10-01", "2013-10-29", "2013-11-26"])
assert frequencies.infer_freq(index) != "WOM-4TUE"
def test_fifth_week_of_month():
# see gh-9425
#
# Only supports freq up to WOM-4.
msg = (
"Of the four parameters: start, end, periods, "
"and freq, exactly three must be specified"
)
with pytest.raises(ValueError, match=msg):
date_range("2014-01-01", freq="WOM-5MON")
def test_monthly_ambiguous():
rng = DatetimeIndex(["1/31/2000", "2/29/2000", "3/31/2000"])
assert rng.inferred_freq == "M"
def test_annual_ambiguous():
rng = DatetimeIndex(["1/31/2000", "1/31/2001", "1/31/2002"])
assert rng.inferred_freq == "A-JAN"
def test_infer_freq_delta(base_delta_code_pair, count):
b = Timestamp(datetime.now())
base_delta, code = base_delta_code_pair
inc = base_delta * count
index = DatetimeIndex([b + inc * j for j in range(3)])
exp_freq = "{count:d}{code}".format(count=count, code=code) if count > 1 else code
assert frequencies.infer_freq(index) == exp_freq
@pytest.mark.parametrize(
"constructor",
[
lambda now, delta: DatetimeIndex(
[now + delta * 7] + [now + delta * j for j in range(3)]
),
lambda now, delta: DatetimeIndex(
[now + delta * j for j in range(3)] + [now + delta * 7]
),
],
)
def test_infer_freq_custom(base_delta_code_pair, constructor):
b = Timestamp(datetime.now())
base_delta, _ = base_delta_code_pair
index = constructor(b, base_delta)
assert frequencies.infer_freq(index) is None
def test_weekly_infer(periods, day):
_check_generated_range("1/1/2000", periods, "W-{day}".format(day=day))
def test_week_of_month_infer(periods, day, count):
_check_generated_range(
"1/1/2000", periods, "WOM-{count}{day}".format(count=count, day=day)
)
@pytest.mark.parametrize("freq", ["M", "BM", "BMS"])
def test_monthly_infer(periods, freq):
_check_generated_range("1/1/2000", periods, "M")
def test_quarterly_infer(month, periods):
_check_generated_range("1/1/2000", periods, "Q-{month}".format(month=month))
@pytest.mark.parametrize("annual", ["A", "BA"])
def test_annually_infer(month, periods, annual):
_check_generated_range(
"1/1/2000", periods, "{annual}-{month}".format(annual=annual, month=month)
)
@pytest.mark.parametrize(
"freq,expected", [("Q", "Q-DEC"), ("Q-NOV", "Q-NOV"), ("Q-OCT", "Q-OCT")]
)
def test_infer_freq_index(freq, expected):
rng = period_range("1959Q2", "2009Q3", freq=freq)
rng = Index(rng.to_timestamp("D", how="e").astype(object))
assert rng.inferred_freq == expected
@pytest.mark.parametrize(
"expected,dates",
list(
{
"AS-JAN": ["2009-01-01", "2010-01-01", "2011-01-01", "2012-01-01"],
"Q-OCT": ["2009-01-31", "2009-04-30", "2009-07-31", "2009-10-31"],
"M": ["2010-11-30", "2010-12-31", "2011-01-31", "2011-02-28"],
"W-SAT": ["2010-12-25", "2011-01-01", "2011-01-08", "2011-01-15"],
"D": ["2011-01-01", "2011-01-02", "2011-01-03", "2011-01-04"],
"H": [
"2011-12-31 22:00",
"2011-12-31 23:00",
"2012-01-01 00:00",
"2012-01-01 01:00",
],
}.items()
),
)
def test_infer_freq_tz(tz_naive_fixture, expected, dates):
# see gh-7310
tz = tz_naive_fixture
idx = DatetimeIndex(dates, tz=tz)
assert idx.inferred_freq == expected
@pytest.mark.parametrize(
"date_pair",
[
["2013-11-02", "2013-11-5"], # Fall DST
["2014-03-08", "2014-03-11"], # Spring DST
["2014-01-01", "2014-01-03"], # Regular Time
],
)
@pytest.mark.parametrize(
"freq", ["3H", "10T", "3601S", "3600001L", "3600000001U", "3600000000001N"]
)
def test_infer_freq_tz_transition(tz_naive_fixture, date_pair, freq):
# see gh-8772
tz = tz_naive_fixture
idx = date_range(date_pair[0], date_pair[1], freq=freq, tz=tz)
assert idx.inferred_freq == freq
def test_infer_freq_tz_transition_custom():
index = date_range("2013-11-03", periods=5, freq="3H").tz_localize(
"America/Chicago"
)
assert index.inferred_freq is None
@pytest.mark.parametrize(
"data,expected",
[
# Hourly freq in a day must result in "H"
(
[
"2014-07-01 09:00",
"2014-07-01 10:00",
"2014-07-01 11:00",
"2014-07-01 12:00",
"2014-07-01 13:00",
"2014-07-01 14:00",
],
"H",
),
(
[
"2014-07-01 09:00",
"2014-07-01 10:00",
"2014-07-01 11:00",
"2014-07-01 12:00",
"2014-07-01 13:00",
"2014-07-01 14:00",
"2014-07-01 15:00",
"2014-07-01 16:00",
"2014-07-02 09:00",
"2014-07-02 10:00",
"2014-07-02 11:00",
],
"BH",
),
(
[
"2014-07-04 09:00",
"2014-07-04 10:00",
"2014-07-04 11:00",
"2014-07-04 12:00",
"2014-07-04 13:00",
"2014-07-04 14:00",
"2014-07-04 15:00",
"2014-07-04 16:00",
"2014-07-07 09:00",
"2014-07-07 10:00",
"2014-07-07 11:00",
],
"BH",
),
(
[
"2014-07-04 09:00",
"2014-07-04 10:00",
"2014-07-04 11:00",
"2014-07-04 12:00",
"2014-07-04 13:00",
"2014-07-04 14:00",
"2014-07-04 15:00",
"2014-07-04 16:00",
"2014-07-07 09:00",
"2014-07-07 10:00",
"2014-07-07 11:00",
"2014-07-07 12:00",
"2014-07-07 13:00",
"2014-07-07 14:00",
"2014-07-07 15:00",
"2014-07-07 16:00",
"2014-07-08 09:00",
"2014-07-08 10:00",
"2014-07-08 11:00",
"2014-07-08 12:00",
"2014-07-08 13:00",
"2014-07-08 14:00",
"2014-07-08 15:00",
"2014-07-08 16:00",
],
"BH",
),
],
)
def test_infer_freq_business_hour(data, expected):
# see gh-7905
idx = DatetimeIndex(data)
assert idx.inferred_freq == expected
def test_not_monotonic():
rng = DatetimeIndex(["1/31/2000", "1/31/2001", "1/31/2002"])
rng = rng[::-1]
assert rng.inferred_freq == "-1A-JAN"
def test_non_datetime_index2():
rng = DatetimeIndex(["1/31/2000", "1/31/2001", "1/31/2002"])
vals = rng.to_pydatetime()
result = frequencies.infer_freq(vals)
assert result == rng.inferred_freq
@pytest.mark.parametrize(
"idx", [tm.makeIntIndex(10), tm.makeFloatIndex(10), tm.makePeriodIndex(10)]
)
def test_invalid_index_types(idx):
msg = (
"(cannot infer freq from a non-convertible)|"
"(Check the `freq` attribute instead of using infer_freq)"
)
with pytest.raises(TypeError, match=msg):
frequencies.infer_freq(idx)
@pytest.mark.skipif(is_platform_windows(), reason="see gh-10822: Windows issue")
@pytest.mark.parametrize("idx", [tm.makeStringIndex(10), tm.makeUnicodeIndex(10)])
def test_invalid_index_types_unicode(idx):
# see gh-10822
#
# Odd error message on conversions to datetime for unicode.
msg = "Unknown string format"
with pytest.raises(ValueError, match=msg):
frequencies.infer_freq(idx)
def test_string_datetime_like_compat():
# see gh-6463
data = ["2004-01", "2004-02", "2004-03", "2004-04"]
expected = frequencies.infer_freq(data)
result = frequencies.infer_freq(Index(data))
assert result == expected
def test_series():
# see gh-6407
s = Series(date_range("20130101", "20130110"))
inferred = frequencies.infer_freq(s)
assert inferred == "D"
@pytest.mark.parametrize("end", [10, 10.0])
def test_series_invalid_type(end):
# see gh-6407
msg = "cannot infer freq from a non-convertible dtype on a Series"
s = Series(np.arange(end))
with pytest.raises(TypeError, match=msg):
frequencies.infer_freq(s)
def test_series_inconvertible_string():
# see gh-6407
msg = "Unknown string format"
with pytest.raises(ValueError, match=msg):
frequencies.infer_freq(Series(["foo", "bar"]))
@pytest.mark.parametrize("freq", [None, "L"])
def test_series_period_index(freq):
# see gh-6407
#
# Cannot infer on PeriodIndex
msg = "cannot infer freq from a non-convertible dtype on a Series"
s = Series(period_range("2013", periods=10, freq=freq))
with pytest.raises(TypeError, match=msg):
frequencies.infer_freq(s)
@pytest.mark.parametrize("freq", ["M", "L", "S"])
def test_series_datetime_index(freq):
s = Series(date_range("20130101", periods=10, freq=freq))
inferred = frequencies.infer_freq(s)
assert inferred == freq
@pytest.mark.parametrize(
"offset_func",
[
frequencies.get_offset,
lambda freq: date_range("2011-01-01", periods=5, freq=freq),
],
)
@pytest.mark.parametrize(
"freq",
[
"WEEKDAY",
"EOM",
"W@MON",
"W@TUE",
"W@WED",
"W@THU",
"W@FRI",
"W@SAT",
"W@SUN",
"Q@JAN",
"Q@FEB",
"Q@MAR",
"A@JAN",
"A@FEB",
"A@MAR",
"A@APR",
"A@MAY",
"A@JUN",
"A@JUL",
"A@AUG",
"A@SEP",
"A@OCT",
"A@NOV",
"A@DEC",
"Y@JAN",
"WOM@1MON",
"WOM@2MON",
"WOM@3MON",
"WOM@4MON",
"WOM@1TUE",
"WOM@2TUE",
"WOM@3TUE",
"WOM@4TUE",
"WOM@1WED",
"WOM@2WED",
"WOM@3WED",
"WOM@4WED",
"WOM@1THU",
"WOM@2THU",
"WOM@3THU",
"WOM@4THU",
"WOM@1FRI",
"WOM@2FRI",
"WOM@3FRI",
"WOM@4FRI",
],
)
def test_legacy_offset_warnings(offset_func, freq):
with pytest.raises(ValueError, match=INVALID_FREQ_ERR_MSG):
offset_func(freq)
def test_ms_vs_capital_ms():
left = frequencies.get_offset("ms")
right = frequencies.get_offset("MS")
assert left == offsets.Milli()
assert right == offsets.MonthBegin()

View File

@@ -0,0 +1,176 @@
import re
import pytest
from pandas import Timedelta
import pandas.tseries.frequencies as frequencies
import pandas.tseries.offsets as offsets
@pytest.mark.parametrize(
"freq_input,expected",
[
(frequencies.to_offset("10us"), offsets.Micro(10)),
(offsets.Hour(), offsets.Hour()),
((5, "T"), offsets.Minute(5)),
("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)),
("15l500u", offsets.Micro(15500)),
("10s75L", offsets.Milli(10075)),
("1s0.25ms", offsets.Micro(1000250)),
("1s0.25L", offsets.Micro(1000250)),
("2800N", offsets.Nano(2800)),
("2SM", offsets.SemiMonthEnd(2)),
("2SM-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 = frequencies.to_offset(freq_input)
assert result == expected
@pytest.mark.parametrize(
"freqstr,expected", [("-1S", -1), ("-2SM", -2), ("-1SMS", -1), ("-5min10s", -310)]
)
def test_to_offset_negative(freqstr, expected):
result = frequencies.to_offset(freqstr)
assert result.n == expected
@pytest.mark.parametrize(
"freqstr",
[
"2h20m",
"U1",
"-U",
"3U1",
"-2-3U",
"-2D:3H",
"1.5.0S",
"2SMS-15-15",
"2SMS-15D",
"100foo",
# Invalid leading +/- signs.
"+-1d",
"-+1h",
"+1",
"-7",
"+d",
"-m",
# Invalid shortcut anchors.
"SM-0",
"SM-28",
"SM-29",
"SM-FOO",
"BSM",
"SM--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("Invalid frequency: {freqstr}".format(freqstr=freqstr))
with pytest.raises(ValueError, match=msg):
frequencies.to_offset(freqstr)
def test_to_offset_no_evaluate():
with pytest.raises(ValueError, match="Could not evaluate"):
frequencies.to_offset(("", ""))
@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 = frequencies.to_offset(freqstr)
assert result == expected
@pytest.mark.parametrize(
"freqstr,expected", [("00H 00T 01S", 1), ("-00H 03T 14S", -194)]
)
def test_to_offset_leading_zero(freqstr, expected):
result = frequencies.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 = frequencies.to_offset(freqstr)
assert result.n == expected
@pytest.mark.parametrize(
"kwargs,expected",
[
(dict(days=1, seconds=1), offsets.Second(86401)),
(dict(days=-1, seconds=1), offsets.Second(-86399)),
(dict(hours=1, minutes=10), offsets.Minute(70)),
(dict(hours=1, minutes=-10), offsets.Minute(50)),
(dict(weeks=1), offsets.Day(7)),
(dict(hours=1), offsets.Hour(1)),
(dict(hours=1), frequencies.to_offset("60min")),
(dict(microseconds=1), offsets.Micro(1)),
],
)
def test_to_offset_pd_timedelta(kwargs, expected):
# see gh-9064
td = Timedelta(**kwargs)
result = frequencies.to_offset(td)
assert result == expected
def test_to_offset_pd_timedelta_invalid():
# see gh-9064
msg = "Invalid frequency: 0 days 00:00:00"
td = Timedelta(microseconds=0)
with pytest.raises(ValueError, match=msg):
frequencies.to_offset(td)
@pytest.mark.parametrize(
"shortcut,expected",
[
("W", offsets.Week(weekday=6)),
("W-SUN", offsets.Week(weekday=6)),
("Q", offsets.QuarterEnd(startingMonth=12)),
("Q-DEC", offsets.QuarterEnd(startingMonth=12)),
("Q-MAY", offsets.QuarterEnd(startingMonth=5)),
("SM", offsets.SemiMonthEnd(day_of_month=15)),
("SM-15", offsets.SemiMonthEnd(day_of_month=15)),
("SM-1", offsets.SemiMonthEnd(day_of_month=1)),
("SM-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 = frequencies.to_offset(shortcut)
assert result == expected

View File

@@ -0,0 +1,83 @@
from datetime import datetime
import pytest
from pandas import DatetimeIndex
import pandas.util.testing as tm
from pandas.tseries.holiday import (
AbstractHolidayCalendar,
Holiday,
Timestamp,
USFederalHolidayCalendar,
USThanksgivingDay,
get_calendar,
)
@pytest.mark.parametrize(
"transform", [lambda x: x, lambda x: x.strftime("%Y-%m-%d"), lambda x: Timestamp(x)]
)
def test_calendar(transform):
start_date = datetime(2012, 1, 1)
end_date = datetime(2012, 12, 31)
calendar = USFederalHolidayCalendar()
holidays = calendar.holidays(transform(start_date), transform(end_date))
expected = [
datetime(2012, 1, 2),
datetime(2012, 1, 16),
datetime(2012, 2, 20),
datetime(2012, 5, 28),
datetime(2012, 7, 4),
datetime(2012, 9, 3),
datetime(2012, 10, 8),
datetime(2012, 11, 12),
datetime(2012, 11, 22),
datetime(2012, 12, 25),
]
assert list(holidays.to_pydatetime()) == expected
def test_calendar_caching():
# see gh-9552.
class TestCalendar(AbstractHolidayCalendar):
def __init__(self, name=None, rules=None):
super().__init__(name=name, rules=rules)
jan1 = TestCalendar(rules=[Holiday("jan1", year=2015, month=1, day=1)])
jan2 = TestCalendar(rules=[Holiday("jan2", year=2015, month=1, day=2)])
# Getting holidays for Jan 1 should not alter results for Jan 2.
tm.assert_index_equal(jan1.holidays(), DatetimeIndex(["01-Jan-2015"]))
tm.assert_index_equal(jan2.holidays(), DatetimeIndex(["02-Jan-2015"]))
def test_calendar_observance_dates():
# see gh-11477
us_fed_cal = get_calendar("USFederalHolidayCalendar")
holidays0 = us_fed_cal.holidays(
datetime(2015, 7, 3), datetime(2015, 7, 3)
) # <-- same start and end dates
holidays1 = us_fed_cal.holidays(
datetime(2015, 7, 3), datetime(2015, 7, 6)
) # <-- different start and end dates
holidays2 = us_fed_cal.holidays(
datetime(2015, 7, 3), datetime(2015, 7, 3)
) # <-- same start and end dates
# These should all produce the same result.
#
# In addition, calling with different start and end
# dates should not alter the output if we call the
# function again with the same start and end date.
tm.assert_index_equal(holidays0, holidays1)
tm.assert_index_equal(holidays0, holidays2)
def test_rule_from_name():
us_fed_cal = get_calendar("USFederalHolidayCalendar")
assert us_fed_cal.rule_from_name("Thanksgiving") == USThanksgivingDay

View File

@@ -0,0 +1,38 @@
from datetime import datetime
from pandas.tseries.holiday import (
AbstractHolidayCalendar,
USMartinLutherKingJr,
USMemorialDay,
)
def test_no_mlk_before_1986():
# see gh-10278
class MLKCalendar(AbstractHolidayCalendar):
rules = [USMartinLutherKingJr]
holidays = MLKCalendar().holidays(start="1984", end="1988").to_pydatetime().tolist()
# Testing to make sure holiday is not incorrectly observed before 1986.
assert holidays == [datetime(1986, 1, 20, 0, 0), datetime(1987, 1, 19, 0, 0)]
def test_memorial_day():
class MemorialDay(AbstractHolidayCalendar):
rules = [USMemorialDay]
holidays = MemorialDay().holidays(start="1971", end="1980").to_pydatetime().tolist()
# Fixes 5/31 error and checked manually against Wikipedia.
assert holidays == [
datetime(1971, 5, 31, 0, 0),
datetime(1972, 5, 29, 0, 0),
datetime(1973, 5, 28, 0, 0),
datetime(1974, 5, 27, 0, 0),
datetime(1975, 5, 26, 0, 0),
datetime(1976, 5, 31, 0, 0),
datetime(1977, 5, 30, 0, 0),
datetime(1978, 5, 29, 0, 0),
datetime(1979, 5, 28, 0, 0),
]

View File

@@ -0,0 +1,268 @@
from datetime import datetime
import pytest
from pytz import utc
import pandas.util.testing as tm
from pandas.tseries.holiday import (
MO,
SA,
AbstractHolidayCalendar,
DateOffset,
EasterMonday,
GoodFriday,
Holiday,
HolidayCalendarFactory,
Timestamp,
USColumbusDay,
USLaborDay,
USMartinLutherKingJr,
USMemorialDay,
USPresidentsDay,
USThanksgivingDay,
get_calendar,
next_monday,
)
def _check_holiday_results(holiday, start, end, expected):
"""
Check that the dates for a given holiday match in date and timezone.
Parameters
----------
holiday : Holiday
The holiday to check.
start : datetime-like
The start date of range in which to collect dates for a given holiday.
end : datetime-like
The end date of range in which to collect dates for a given holiday.
expected : list
The list of dates we expect to get.
"""
assert list(holiday.dates(start, end)) == expected
# Verify that timezone info is preserved.
assert list(
holiday.dates(utc.localize(Timestamp(start)), utc.localize(Timestamp(end)))
) == [utc.localize(dt) for dt in expected]
@pytest.mark.parametrize(
"holiday,start_date,end_date,expected",
[
(
USMemorialDay,
datetime(2011, 1, 1),
datetime(2020, 12, 31),
[
datetime(2011, 5, 30),
datetime(2012, 5, 28),
datetime(2013, 5, 27),
datetime(2014, 5, 26),
datetime(2015, 5, 25),
datetime(2016, 5, 30),
datetime(2017, 5, 29),
datetime(2018, 5, 28),
datetime(2019, 5, 27),
datetime(2020, 5, 25),
],
),
(
Holiday("July 4th Eve", month=7, day=3),
"2001-01-01",
"2003-03-03",
[Timestamp("2001-07-03 00:00:00"), Timestamp("2002-07-03 00:00:00")],
),
(
Holiday("July 4th Eve", month=7, day=3, days_of_week=(0, 1, 2, 3)),
"2001-01-01",
"2008-03-03",
[
Timestamp("2001-07-03 00:00:00"),
Timestamp("2002-07-03 00:00:00"),
Timestamp("2003-07-03 00:00:00"),
Timestamp("2006-07-03 00:00:00"),
Timestamp("2007-07-03 00:00:00"),
],
),
(
EasterMonday,
datetime(2011, 1, 1),
datetime(2020, 12, 31),
[
Timestamp("2011-04-25 00:00:00"),
Timestamp("2012-04-09 00:00:00"),
Timestamp("2013-04-01 00:00:00"),
Timestamp("2014-04-21 00:00:00"),
Timestamp("2015-04-06 00:00:00"),
Timestamp("2016-03-28 00:00:00"),
Timestamp("2017-04-17 00:00:00"),
Timestamp("2018-04-02 00:00:00"),
Timestamp("2019-04-22 00:00:00"),
Timestamp("2020-04-13 00:00:00"),
],
),
(
GoodFriday,
datetime(2011, 1, 1),
datetime(2020, 12, 31),
[
Timestamp("2011-04-22 00:00:00"),
Timestamp("2012-04-06 00:00:00"),
Timestamp("2013-03-29 00:00:00"),
Timestamp("2014-04-18 00:00:00"),
Timestamp("2015-04-03 00:00:00"),
Timestamp("2016-03-25 00:00:00"),
Timestamp("2017-04-14 00:00:00"),
Timestamp("2018-03-30 00:00:00"),
Timestamp("2019-04-19 00:00:00"),
Timestamp("2020-04-10 00:00:00"),
],
),
(
USThanksgivingDay,
datetime(2011, 1, 1),
datetime(2020, 12, 31),
[
datetime(2011, 11, 24),
datetime(2012, 11, 22),
datetime(2013, 11, 28),
datetime(2014, 11, 27),
datetime(2015, 11, 26),
datetime(2016, 11, 24),
datetime(2017, 11, 23),
datetime(2018, 11, 22),
datetime(2019, 11, 28),
datetime(2020, 11, 26),
],
),
],
)
def test_holiday_dates(holiday, start_date, end_date, expected):
_check_holiday_results(holiday, start_date, end_date, expected)
@pytest.mark.parametrize(
"holiday,start,expected",
[
(USMemorialDay, datetime(2015, 7, 1), []),
(USMemorialDay, "2015-05-25", "2015-05-25"),
(USLaborDay, datetime(2015, 7, 1), []),
(USLaborDay, "2015-09-07", "2015-09-07"),
(USColumbusDay, datetime(2015, 7, 1), []),
(USColumbusDay, "2015-10-12", "2015-10-12"),
(USThanksgivingDay, datetime(2015, 7, 1), []),
(USThanksgivingDay, "2015-11-26", "2015-11-26"),
(USMartinLutherKingJr, datetime(2015, 7, 1), []),
(USMartinLutherKingJr, "2015-01-19", "2015-01-19"),
(USPresidentsDay, datetime(2015, 7, 1), []),
(USPresidentsDay, "2015-02-16", "2015-02-16"),
(GoodFriday, datetime(2015, 7, 1), []),
(GoodFriday, "2015-04-03", "2015-04-03"),
(EasterMonday, "2015-04-06", "2015-04-06"),
(EasterMonday, datetime(2015, 7, 1), []),
(EasterMonday, "2015-04-05", []),
("New Years Day", "2015-01-01", "2015-01-01"),
("New Years Day", "2010-12-31", "2010-12-31"),
("New Years Day", datetime(2015, 7, 1), []),
("New Years Day", "2011-01-01", []),
("July 4th", "2015-07-03", "2015-07-03"),
("July 4th", datetime(2015, 7, 1), []),
("July 4th", "2015-07-04", []),
("Veterans Day", "2012-11-12", "2012-11-12"),
("Veterans Day", datetime(2015, 7, 1), []),
("Veterans Day", "2012-11-11", []),
("Christmas", "2011-12-26", "2011-12-26"),
("Christmas", datetime(2015, 7, 1), []),
("Christmas", "2011-12-25", []),
],
)
def test_holidays_within_dates(holiday, start, expected):
# see gh-11477
#
# Fix holiday behavior where holiday.dates returned dates outside
# start/end date, or observed rules could not be applied because the
# holiday was not in the original date range (e.g., 7/4/2015 -> 7/3/2015).
if isinstance(holiday, str):
calendar = get_calendar("USFederalHolidayCalendar")
holiday = calendar.rule_from_name(holiday)
if isinstance(expected, str):
expected = [Timestamp(expected)]
_check_holiday_results(holiday, start, start, expected)
@pytest.mark.parametrize(
"transform", [lambda x: x.strftime("%Y-%m-%d"), lambda x: Timestamp(x)]
)
def test_argument_types(transform):
start_date = datetime(2011, 1, 1)
end_date = datetime(2020, 12, 31)
holidays = USThanksgivingDay.dates(start_date, end_date)
holidays2 = USThanksgivingDay.dates(transform(start_date), transform(end_date))
tm.assert_index_equal(holidays, holidays2)
@pytest.mark.parametrize(
"name,kwargs",
[
("One-Time", dict(year=2012, month=5, day=28)),
(
"Range",
dict(
month=5,
day=28,
start_date=datetime(2012, 1, 1),
end_date=datetime(2012, 12, 31),
offset=DateOffset(weekday=MO(1)),
),
),
],
)
def test_special_holidays(name, kwargs):
base_date = [datetime(2012, 5, 28)]
holiday = Holiday(name, **kwargs)
start_date = datetime(2011, 1, 1)
end_date = datetime(2020, 12, 31)
assert base_date == holiday.dates(start_date, end_date)
def test_get_calendar():
class TestCalendar(AbstractHolidayCalendar):
rules = []
calendar = get_calendar("TestCalendar")
assert TestCalendar == calendar.__class__
def test_factory():
class_1 = HolidayCalendarFactory(
"MemorialDay", AbstractHolidayCalendar, USMemorialDay
)
class_2 = HolidayCalendarFactory(
"Thanksgiving", AbstractHolidayCalendar, USThanksgivingDay
)
class_3 = HolidayCalendarFactory("Combined", class_1, class_2)
assert len(class_1.rules) == 1
assert len(class_2.rules) == 1
assert len(class_3.rules) == 2
def test_both_offset_observance_raises():
# see gh-10217
msg = "Cannot use both offset and observance"
with pytest.raises(NotImplementedError, match=msg):
Holiday(
"Cyber Monday",
month=11,
day=1,
offset=[DateOffset(weekday=SA(4))],
observance=next_monday,
)

View File

@@ -0,0 +1,87 @@
from datetime import datetime
import pytest
from pandas.tseries.holiday import (
after_nearest_workday,
before_nearest_workday,
nearest_workday,
next_monday,
next_monday_or_tuesday,
next_workday,
previous_friday,
previous_workday,
sunday_to_monday,
weekend_to_monday,
)
_WEDNESDAY = datetime(2014, 4, 9)
_THURSDAY = datetime(2014, 4, 10)
_FRIDAY = datetime(2014, 4, 11)
_SATURDAY = datetime(2014, 4, 12)
_SUNDAY = datetime(2014, 4, 13)
_MONDAY = datetime(2014, 4, 14)
_TUESDAY = datetime(2014, 4, 15)
@pytest.mark.parametrize("day", [_SATURDAY, _SUNDAY])
def test_next_monday(day):
assert next_monday(day) == _MONDAY
@pytest.mark.parametrize(
"day,expected", [(_SATURDAY, _MONDAY), (_SUNDAY, _TUESDAY), (_MONDAY, _TUESDAY)]
)
def test_next_monday_or_tuesday(day, expected):
assert next_monday_or_tuesday(day) == expected
@pytest.mark.parametrize("day", [_SATURDAY, _SUNDAY])
def test_previous_friday(day):
assert previous_friday(day) == _FRIDAY
def test_sunday_to_monday():
assert sunday_to_monday(_SUNDAY) == _MONDAY
@pytest.mark.parametrize(
"day,expected", [(_SATURDAY, _FRIDAY), (_SUNDAY, _MONDAY), (_MONDAY, _MONDAY)]
)
def test_nearest_workday(day, expected):
assert nearest_workday(day) == expected
@pytest.mark.parametrize(
"day,expected", [(_SATURDAY, _MONDAY), (_SUNDAY, _MONDAY), (_MONDAY, _MONDAY)]
)
def test_weekend_to_monday(day, expected):
assert weekend_to_monday(day) == expected
@pytest.mark.parametrize(
"day,expected", [(_SATURDAY, _MONDAY), (_SUNDAY, _MONDAY), (_MONDAY, _TUESDAY)]
)
def test_next_workday(day, expected):
assert next_workday(day) == expected
@pytest.mark.parametrize(
"day,expected", [(_SATURDAY, _FRIDAY), (_SUNDAY, _FRIDAY), (_TUESDAY, _MONDAY)]
)
def test_previous_workday(day, expected):
assert previous_workday(day) == expected
@pytest.mark.parametrize(
"day,expected", [(_SATURDAY, _THURSDAY), (_SUNDAY, _FRIDAY), (_TUESDAY, _MONDAY)]
)
def test_before_nearest_workday(day, expected):
assert before_nearest_workday(day) == expected
@pytest.mark.parametrize(
"day,expected", [(_SATURDAY, _MONDAY), (_SUNDAY, _TUESDAY), (_FRIDAY, _MONDAY)]
)
def test_after_nearest_workday(day, expected):
assert after_nearest_workday(day) == expected

View File

@@ -0,0 +1,30 @@
"""
Assertion helpers for offsets tests
"""
def assert_offset_equal(offset, base, expected):
actual = offset + base
actual_swapped = base + offset
actual_apply = offset.apply(base)
try:
assert actual == expected
assert actual_swapped == expected
assert actual_apply == expected
except AssertionError:
raise AssertionError(
"\nExpected: {expected}\nActual: {actual}\nFor Offset: {offset})"
"\nAt Date: {base}".format(
expected=expected, actual=actual, offset=offset, base=base
)
)
def assert_onOffset(offset, date, expected):
actual = offset.onOffset(date)
assert actual == expected, (
"\nExpected: {expected}\nActual: {actual}\nFor Offset: {offset})"
"\nAt Date: {date}".format(
expected=expected, actual=actual, offset=offset, date=date
)
)

View File

@@ -0,0 +1,25 @@
import pytest
import pandas.tseries.offsets as offsets
@pytest.fixture(params=[getattr(offsets, o) for o in offsets.__all__])
def offset_types(request):
"""
Fixture for all the datetime offsets available for a time series.
"""
return request.param
@pytest.fixture(
params=[
getattr(offsets, o)
for o in offsets.__all__
if issubclass(getattr(offsets, o), offsets.MonthOffset) and o != "MonthOffset"
]
)
def month_classes(request):
"""
Fixture for month based datetime offsets available for a time series.
"""
return request.param

View File

@@ -0,0 +1,689 @@
"""
Tests for Fiscal Year and Fiscal Quarter offset classes
"""
from datetime import datetime
from dateutil.relativedelta import relativedelta
import pytest
from pandas._libs.tslibs.frequencies import INVALID_FREQ_ERR_MSG
from pandas import Timestamp
from pandas.tseries.frequencies import get_offset
from pandas.tseries.offsets import FY5253, FY5253Quarter
from .common import assert_offset_equal, assert_onOffset
from .test_offsets import Base, WeekDay
def makeFY5253LastOfMonthQuarter(*args, **kwds):
return FY5253Quarter(*args, variation="last", **kwds)
def makeFY5253NearestEndMonthQuarter(*args, **kwds):
return FY5253Quarter(*args, variation="nearest", **kwds)
def makeFY5253NearestEndMonth(*args, **kwds):
return FY5253(*args, variation="nearest", **kwds)
def makeFY5253LastOfMonth(*args, **kwds):
return FY5253(*args, variation="last", **kwds)
def test_get_offset_name():
assert (
makeFY5253LastOfMonthQuarter(
weekday=1, startingMonth=3, qtr_with_extra_week=4
).freqstr
== "REQ-L-MAR-TUE-4"
)
assert (
makeFY5253NearestEndMonthQuarter(
weekday=1, startingMonth=3, qtr_with_extra_week=3
).freqstr
== "REQ-N-MAR-TUE-3"
)
def test_get_offset():
with pytest.raises(ValueError, match=INVALID_FREQ_ERR_MSG):
get_offset("gibberish")
with pytest.raises(ValueError, match=INVALID_FREQ_ERR_MSG):
get_offset("QS-JAN-B")
pairs = [
("RE-N-DEC-MON", makeFY5253NearestEndMonth(weekday=0, startingMonth=12)),
("RE-L-DEC-TUE", makeFY5253LastOfMonth(weekday=1, startingMonth=12)),
(
"REQ-L-MAR-TUE-4",
makeFY5253LastOfMonthQuarter(
weekday=1, startingMonth=3, qtr_with_extra_week=4
),
),
(
"REQ-L-DEC-MON-3",
makeFY5253LastOfMonthQuarter(
weekday=0, startingMonth=12, qtr_with_extra_week=3
),
),
(
"REQ-N-DEC-MON-3",
makeFY5253NearestEndMonthQuarter(
weekday=0, startingMonth=12, qtr_with_extra_week=3
),
),
]
for name, expected in pairs:
offset = get_offset(name)
assert (
offset == expected
), "Expected {name!r} to yield {expected!r} (actual: {offset!r})".format(
name=name, expected=expected, offset=offset
)
class TestFY5253LastOfMonth(Base):
offset_lom_sat_aug = makeFY5253LastOfMonth(1, startingMonth=8, weekday=WeekDay.SAT)
offset_lom_sat_sep = makeFY5253LastOfMonth(1, startingMonth=9, weekday=WeekDay.SAT)
on_offset_cases = [
# From Wikipedia (see:
# http://en.wikipedia.org/wiki/4%E2%80%934%E2%80%935_calendar#Last_Saturday_of_the_month_at_fiscal_year_end)
(offset_lom_sat_aug, datetime(2006, 8, 26), True),
(offset_lom_sat_aug, datetime(2007, 8, 25), True),
(offset_lom_sat_aug, datetime(2008, 8, 30), True),
(offset_lom_sat_aug, datetime(2009, 8, 29), True),
(offset_lom_sat_aug, datetime(2010, 8, 28), True),
(offset_lom_sat_aug, datetime(2011, 8, 27), True),
(offset_lom_sat_aug, datetime(2012, 8, 25), True),
(offset_lom_sat_aug, datetime(2013, 8, 31), True),
(offset_lom_sat_aug, datetime(2014, 8, 30), True),
(offset_lom_sat_aug, datetime(2015, 8, 29), True),
(offset_lom_sat_aug, datetime(2016, 8, 27), True),
(offset_lom_sat_aug, datetime(2017, 8, 26), True),
(offset_lom_sat_aug, datetime(2018, 8, 25), True),
(offset_lom_sat_aug, datetime(2019, 8, 31), True),
(offset_lom_sat_aug, datetime(2006, 8, 27), False),
(offset_lom_sat_aug, datetime(2007, 8, 28), False),
(offset_lom_sat_aug, datetime(2008, 8, 31), False),
(offset_lom_sat_aug, datetime(2009, 8, 30), False),
(offset_lom_sat_aug, datetime(2010, 8, 29), False),
(offset_lom_sat_aug, datetime(2011, 8, 28), False),
(offset_lom_sat_aug, datetime(2006, 8, 25), False),
(offset_lom_sat_aug, datetime(2007, 8, 24), False),
(offset_lom_sat_aug, datetime(2008, 8, 29), False),
(offset_lom_sat_aug, datetime(2009, 8, 28), False),
(offset_lom_sat_aug, datetime(2010, 8, 27), False),
(offset_lom_sat_aug, datetime(2011, 8, 26), False),
(offset_lom_sat_aug, datetime(2019, 8, 30), False),
# From GMCR (see for example:
# http://yahoo.brand.edgar-online.com/Default.aspx?
# companyid=3184&formtypeID=7)
(offset_lom_sat_sep, datetime(2010, 9, 25), True),
(offset_lom_sat_sep, datetime(2011, 9, 24), True),
(offset_lom_sat_sep, datetime(2012, 9, 29), True),
]
@pytest.mark.parametrize("case", on_offset_cases)
def test_onOffset(self, case):
offset, dt, expected = case
assert_onOffset(offset, dt, expected)
def test_apply(self):
offset_lom_aug_sat = makeFY5253LastOfMonth(startingMonth=8, weekday=WeekDay.SAT)
offset_lom_aug_sat_1 = makeFY5253LastOfMonth(
n=1, startingMonth=8, weekday=WeekDay.SAT
)
date_seq_lom_aug_sat = [
datetime(2006, 8, 26),
datetime(2007, 8, 25),
datetime(2008, 8, 30),
datetime(2009, 8, 29),
datetime(2010, 8, 28),
datetime(2011, 8, 27),
datetime(2012, 8, 25),
datetime(2013, 8, 31),
datetime(2014, 8, 30),
datetime(2015, 8, 29),
datetime(2016, 8, 27),
]
tests = [
(offset_lom_aug_sat, date_seq_lom_aug_sat),
(offset_lom_aug_sat_1, date_seq_lom_aug_sat),
(offset_lom_aug_sat, [datetime(2006, 8, 25)] + date_seq_lom_aug_sat),
(offset_lom_aug_sat_1, [datetime(2006, 8, 27)] + date_seq_lom_aug_sat[1:]),
(
makeFY5253LastOfMonth(n=-1, startingMonth=8, weekday=WeekDay.SAT),
list(reversed(date_seq_lom_aug_sat)),
),
]
for test in tests:
offset, data = test
current = data[0]
for datum in data[1:]:
current = current + offset
assert current == datum
class TestFY5253NearestEndMonth(Base):
def test_get_year_end(self):
assert makeFY5253NearestEndMonth(
startingMonth=8, weekday=WeekDay.SAT
).get_year_end(datetime(2013, 1, 1)) == datetime(2013, 8, 31)
assert makeFY5253NearestEndMonth(
startingMonth=8, weekday=WeekDay.SUN
).get_year_end(datetime(2013, 1, 1)) == datetime(2013, 9, 1)
assert makeFY5253NearestEndMonth(
startingMonth=8, weekday=WeekDay.FRI
).get_year_end(datetime(2013, 1, 1)) == datetime(2013, 8, 30)
offset_n = FY5253(weekday=WeekDay.TUE, startingMonth=12, variation="nearest")
assert offset_n.get_year_end(datetime(2012, 1, 1)) == datetime(2013, 1, 1)
assert offset_n.get_year_end(datetime(2012, 1, 10)) == datetime(2013, 1, 1)
assert offset_n.get_year_end(datetime(2013, 1, 1)) == datetime(2013, 12, 31)
assert offset_n.get_year_end(datetime(2013, 1, 2)) == datetime(2013, 12, 31)
assert offset_n.get_year_end(datetime(2013, 1, 3)) == datetime(2013, 12, 31)
assert offset_n.get_year_end(datetime(2013, 1, 10)) == datetime(2013, 12, 31)
JNJ = FY5253(n=1, startingMonth=12, weekday=6, variation="nearest")
assert JNJ.get_year_end(datetime(2006, 1, 1)) == datetime(2006, 12, 31)
offset_lom_aug_sat = makeFY5253NearestEndMonth(
1, startingMonth=8, weekday=WeekDay.SAT
)
offset_lom_aug_thu = makeFY5253NearestEndMonth(
1, startingMonth=8, weekday=WeekDay.THU
)
offset_n = FY5253(weekday=WeekDay.TUE, startingMonth=12, variation="nearest")
on_offset_cases = [
# From Wikipedia (see:
# http://en.wikipedia.org/wiki/4%E2%80%934%E2%80%935_calendar
# #Saturday_nearest_the_end_of_month)
# 2006-09-02 2006 September 2
# 2007-09-01 2007 September 1
# 2008-08-30 2008 August 30 (leap year)
# 2009-08-29 2009 August 29
# 2010-08-28 2010 August 28
# 2011-09-03 2011 September 3
# 2012-09-01 2012 September 1 (leap year)
# 2013-08-31 2013 August 31
# 2014-08-30 2014 August 30
# 2015-08-29 2015 August 29
# 2016-09-03 2016 September 3 (leap year)
# 2017-09-02 2017 September 2
# 2018-09-01 2018 September 1
# 2019-08-31 2019 August 31
(offset_lom_aug_sat, datetime(2006, 9, 2), True),
(offset_lom_aug_sat, datetime(2007, 9, 1), True),
(offset_lom_aug_sat, datetime(2008, 8, 30), True),
(offset_lom_aug_sat, datetime(2009, 8, 29), True),
(offset_lom_aug_sat, datetime(2010, 8, 28), True),
(offset_lom_aug_sat, datetime(2011, 9, 3), True),
(offset_lom_aug_sat, datetime(2016, 9, 3), True),
(offset_lom_aug_sat, datetime(2017, 9, 2), True),
(offset_lom_aug_sat, datetime(2018, 9, 1), True),
(offset_lom_aug_sat, datetime(2019, 8, 31), True),
(offset_lom_aug_sat, datetime(2006, 8, 27), False),
(offset_lom_aug_sat, datetime(2007, 8, 28), False),
(offset_lom_aug_sat, datetime(2008, 8, 31), False),
(offset_lom_aug_sat, datetime(2009, 8, 30), False),
(offset_lom_aug_sat, datetime(2010, 8, 29), False),
(offset_lom_aug_sat, datetime(2011, 8, 28), False),
(offset_lom_aug_sat, datetime(2006, 8, 25), False),
(offset_lom_aug_sat, datetime(2007, 8, 24), False),
(offset_lom_aug_sat, datetime(2008, 8, 29), False),
(offset_lom_aug_sat, datetime(2009, 8, 28), False),
(offset_lom_aug_sat, datetime(2010, 8, 27), False),
(offset_lom_aug_sat, datetime(2011, 8, 26), False),
(offset_lom_aug_sat, datetime(2019, 8, 30), False),
# From Micron, see:
# http://google.brand.edgar-online.com/?sym=MU&formtypeID=7
(offset_lom_aug_thu, datetime(2012, 8, 30), True),
(offset_lom_aug_thu, datetime(2011, 9, 1), True),
(offset_n, datetime(2012, 12, 31), False),
(offset_n, datetime(2013, 1, 1), True),
(offset_n, datetime(2013, 1, 2), False),
]
@pytest.mark.parametrize("case", on_offset_cases)
def test_onOffset(self, case):
offset, dt, expected = case
assert_onOffset(offset, dt, expected)
def test_apply(self):
date_seq_nem_8_sat = [
datetime(2006, 9, 2),
datetime(2007, 9, 1),
datetime(2008, 8, 30),
datetime(2009, 8, 29),
datetime(2010, 8, 28),
datetime(2011, 9, 3),
]
JNJ = [
datetime(2005, 1, 2),
datetime(2006, 1, 1),
datetime(2006, 12, 31),
datetime(2007, 12, 30),
datetime(2008, 12, 28),
datetime(2010, 1, 3),
datetime(2011, 1, 2),
datetime(2012, 1, 1),
datetime(2012, 12, 30),
]
DEC_SAT = FY5253(n=-1, startingMonth=12, weekday=5, variation="nearest")
tests = [
(
makeFY5253NearestEndMonth(startingMonth=8, weekday=WeekDay.SAT),
date_seq_nem_8_sat,
),
(
makeFY5253NearestEndMonth(n=1, startingMonth=8, weekday=WeekDay.SAT),
date_seq_nem_8_sat,
),
(
makeFY5253NearestEndMonth(startingMonth=8, weekday=WeekDay.SAT),
[datetime(2006, 9, 1)] + date_seq_nem_8_sat,
),
(
makeFY5253NearestEndMonth(n=1, startingMonth=8, weekday=WeekDay.SAT),
[datetime(2006, 9, 3)] + date_seq_nem_8_sat[1:],
),
(
makeFY5253NearestEndMonth(n=-1, startingMonth=8, weekday=WeekDay.SAT),
list(reversed(date_seq_nem_8_sat)),
),
(
makeFY5253NearestEndMonth(n=1, startingMonth=12, weekday=WeekDay.SUN),
JNJ,
),
(
makeFY5253NearestEndMonth(n=-1, startingMonth=12, weekday=WeekDay.SUN),
list(reversed(JNJ)),
),
(
makeFY5253NearestEndMonth(n=1, startingMonth=12, weekday=WeekDay.SUN),
[datetime(2005, 1, 2), datetime(2006, 1, 1)],
),
(
makeFY5253NearestEndMonth(n=1, startingMonth=12, weekday=WeekDay.SUN),
[datetime(2006, 1, 2), datetime(2006, 12, 31)],
),
(DEC_SAT, [datetime(2013, 1, 15), datetime(2012, 12, 29)]),
]
for test in tests:
offset, data = test
current = data[0]
for datum in data[1:]:
current = current + offset
assert current == datum
class TestFY5253LastOfMonthQuarter(Base):
def test_isAnchored(self):
assert makeFY5253LastOfMonthQuarter(
startingMonth=1, weekday=WeekDay.SAT, qtr_with_extra_week=4
).isAnchored()
assert makeFY5253LastOfMonthQuarter(
weekday=WeekDay.SAT, startingMonth=3, qtr_with_extra_week=4
).isAnchored()
assert not makeFY5253LastOfMonthQuarter(
2, startingMonth=1, weekday=WeekDay.SAT, qtr_with_extra_week=4
).isAnchored()
def test_equality(self):
assert makeFY5253LastOfMonthQuarter(
startingMonth=1, weekday=WeekDay.SAT, qtr_with_extra_week=4
) == makeFY5253LastOfMonthQuarter(
startingMonth=1, weekday=WeekDay.SAT, qtr_with_extra_week=4
)
assert makeFY5253LastOfMonthQuarter(
startingMonth=1, weekday=WeekDay.SAT, qtr_with_extra_week=4
) != makeFY5253LastOfMonthQuarter(
startingMonth=1, weekday=WeekDay.SUN, qtr_with_extra_week=4
)
assert makeFY5253LastOfMonthQuarter(
startingMonth=1, weekday=WeekDay.SAT, qtr_with_extra_week=4
) != makeFY5253LastOfMonthQuarter(
startingMonth=2, weekday=WeekDay.SAT, qtr_with_extra_week=4
)
def test_offset(self):
offset = makeFY5253LastOfMonthQuarter(
1, startingMonth=9, weekday=WeekDay.SAT, qtr_with_extra_week=4
)
offset2 = makeFY5253LastOfMonthQuarter(
2, startingMonth=9, weekday=WeekDay.SAT, qtr_with_extra_week=4
)
offset4 = makeFY5253LastOfMonthQuarter(
4, startingMonth=9, weekday=WeekDay.SAT, qtr_with_extra_week=4
)
offset_neg1 = makeFY5253LastOfMonthQuarter(
-1, startingMonth=9, weekday=WeekDay.SAT, qtr_with_extra_week=4
)
offset_neg2 = makeFY5253LastOfMonthQuarter(
-2, startingMonth=9, weekday=WeekDay.SAT, qtr_with_extra_week=4
)
GMCR = [
datetime(2010, 3, 27),
datetime(2010, 6, 26),
datetime(2010, 9, 25),
datetime(2010, 12, 25),
datetime(2011, 3, 26),
datetime(2011, 6, 25),
datetime(2011, 9, 24),
datetime(2011, 12, 24),
datetime(2012, 3, 24),
datetime(2012, 6, 23),
datetime(2012, 9, 29),
datetime(2012, 12, 29),
datetime(2013, 3, 30),
datetime(2013, 6, 29),
]
assert_offset_equal(offset, base=GMCR[0], expected=GMCR[1])
assert_offset_equal(
offset, base=GMCR[0] + relativedelta(days=-1), expected=GMCR[0]
)
assert_offset_equal(offset, base=GMCR[1], expected=GMCR[2])
assert_offset_equal(offset2, base=GMCR[0], expected=GMCR[2])
assert_offset_equal(offset4, base=GMCR[0], expected=GMCR[4])
assert_offset_equal(offset_neg1, base=GMCR[-1], expected=GMCR[-2])
assert_offset_equal(
offset_neg1, base=GMCR[-1] + relativedelta(days=+1), expected=GMCR[-1]
)
assert_offset_equal(offset_neg2, base=GMCR[-1], expected=GMCR[-3])
date = GMCR[0] + relativedelta(days=-1)
for expected in GMCR:
assert_offset_equal(offset, date, expected)
date = date + offset
date = GMCR[-1] + relativedelta(days=+1)
for expected in reversed(GMCR):
assert_offset_equal(offset_neg1, date, expected)
date = date + offset_neg1
lomq_aug_sat_4 = makeFY5253LastOfMonthQuarter(
1, startingMonth=8, weekday=WeekDay.SAT, qtr_with_extra_week=4
)
lomq_sep_sat_4 = makeFY5253LastOfMonthQuarter(
1, startingMonth=9, weekday=WeekDay.SAT, qtr_with_extra_week=4
)
on_offset_cases = [
# From Wikipedia
(lomq_aug_sat_4, datetime(2006, 8, 26), True),
(lomq_aug_sat_4, datetime(2007, 8, 25), True),
(lomq_aug_sat_4, datetime(2008, 8, 30), True),
(lomq_aug_sat_4, datetime(2009, 8, 29), True),
(lomq_aug_sat_4, datetime(2010, 8, 28), True),
(lomq_aug_sat_4, datetime(2011, 8, 27), True),
(lomq_aug_sat_4, datetime(2019, 8, 31), True),
(lomq_aug_sat_4, datetime(2006, 8, 27), False),
(lomq_aug_sat_4, datetime(2007, 8, 28), False),
(lomq_aug_sat_4, datetime(2008, 8, 31), False),
(lomq_aug_sat_4, datetime(2009, 8, 30), False),
(lomq_aug_sat_4, datetime(2010, 8, 29), False),
(lomq_aug_sat_4, datetime(2011, 8, 28), False),
(lomq_aug_sat_4, datetime(2006, 8, 25), False),
(lomq_aug_sat_4, datetime(2007, 8, 24), False),
(lomq_aug_sat_4, datetime(2008, 8, 29), False),
(lomq_aug_sat_4, datetime(2009, 8, 28), False),
(lomq_aug_sat_4, datetime(2010, 8, 27), False),
(lomq_aug_sat_4, datetime(2011, 8, 26), False),
(lomq_aug_sat_4, datetime(2019, 8, 30), False),
# From GMCR
(lomq_sep_sat_4, datetime(2010, 9, 25), True),
(lomq_sep_sat_4, datetime(2011, 9, 24), True),
(lomq_sep_sat_4, datetime(2012, 9, 29), True),
(lomq_sep_sat_4, datetime(2013, 6, 29), True),
(lomq_sep_sat_4, datetime(2012, 6, 23), True),
(lomq_sep_sat_4, datetime(2012, 6, 30), False),
(lomq_sep_sat_4, datetime(2013, 3, 30), True),
(lomq_sep_sat_4, datetime(2012, 3, 24), True),
(lomq_sep_sat_4, datetime(2012, 12, 29), True),
(lomq_sep_sat_4, datetime(2011, 12, 24), True),
# INTC (extra week in Q1)
# See: http://www.intc.com/releasedetail.cfm?ReleaseID=542844
(
makeFY5253LastOfMonthQuarter(
1, startingMonth=12, weekday=WeekDay.SAT, qtr_with_extra_week=1
),
datetime(2011, 4, 2),
True,
),
# see: http://google.brand.edgar-online.com/?sym=INTC&formtypeID=7
(
makeFY5253LastOfMonthQuarter(
1, startingMonth=12, weekday=WeekDay.SAT, qtr_with_extra_week=1
),
datetime(2012, 12, 29),
True,
),
(
makeFY5253LastOfMonthQuarter(
1, startingMonth=12, weekday=WeekDay.SAT, qtr_with_extra_week=1
),
datetime(2011, 12, 31),
True,
),
(
makeFY5253LastOfMonthQuarter(
1, startingMonth=12, weekday=WeekDay.SAT, qtr_with_extra_week=1
),
datetime(2010, 12, 25),
True,
),
]
@pytest.mark.parametrize("case", on_offset_cases)
def test_onOffset(self, case):
offset, dt, expected = case
assert_onOffset(offset, dt, expected)
def test_year_has_extra_week(self):
# End of long Q1
assert makeFY5253LastOfMonthQuarter(
1, startingMonth=12, weekday=WeekDay.SAT, qtr_with_extra_week=1
).year_has_extra_week(datetime(2011, 4, 2))
# Start of long Q1
assert makeFY5253LastOfMonthQuarter(
1, startingMonth=12, weekday=WeekDay.SAT, qtr_with_extra_week=1
).year_has_extra_week(datetime(2010, 12, 26))
# End of year before year with long Q1
assert not makeFY5253LastOfMonthQuarter(
1, startingMonth=12, weekday=WeekDay.SAT, qtr_with_extra_week=1
).year_has_extra_week(datetime(2010, 12, 25))
for year in [
x for x in range(1994, 2011 + 1) if x not in [2011, 2005, 2000, 1994]
]:
assert not makeFY5253LastOfMonthQuarter(
1, startingMonth=12, weekday=WeekDay.SAT, qtr_with_extra_week=1
).year_has_extra_week(datetime(year, 4, 2))
# Other long years
assert makeFY5253LastOfMonthQuarter(
1, startingMonth=12, weekday=WeekDay.SAT, qtr_with_extra_week=1
).year_has_extra_week(datetime(2005, 4, 2))
assert makeFY5253LastOfMonthQuarter(
1, startingMonth=12, weekday=WeekDay.SAT, qtr_with_extra_week=1
).year_has_extra_week(datetime(2000, 4, 2))
assert makeFY5253LastOfMonthQuarter(
1, startingMonth=12, weekday=WeekDay.SAT, qtr_with_extra_week=1
).year_has_extra_week(datetime(1994, 4, 2))
def test_get_weeks(self):
sat_dec_1 = makeFY5253LastOfMonthQuarter(
1, startingMonth=12, weekday=WeekDay.SAT, qtr_with_extra_week=1
)
sat_dec_4 = makeFY5253LastOfMonthQuarter(
1, startingMonth=12, weekday=WeekDay.SAT, qtr_with_extra_week=4
)
assert sat_dec_1.get_weeks(datetime(2011, 4, 2)) == [14, 13, 13, 13]
assert sat_dec_4.get_weeks(datetime(2011, 4, 2)) == [13, 13, 13, 14]
assert sat_dec_1.get_weeks(datetime(2010, 12, 25)) == [13, 13, 13, 13]
class TestFY5253NearestEndMonthQuarter(Base):
offset_nem_sat_aug_4 = makeFY5253NearestEndMonthQuarter(
1, startingMonth=8, weekday=WeekDay.SAT, qtr_with_extra_week=4
)
offset_nem_thu_aug_4 = makeFY5253NearestEndMonthQuarter(
1, startingMonth=8, weekday=WeekDay.THU, qtr_with_extra_week=4
)
offset_n = FY5253(weekday=WeekDay.TUE, startingMonth=12, variation="nearest")
on_offset_cases = [
# From Wikipedia
(offset_nem_sat_aug_4, datetime(2006, 9, 2), True),
(offset_nem_sat_aug_4, datetime(2007, 9, 1), True),
(offset_nem_sat_aug_4, datetime(2008, 8, 30), True),
(offset_nem_sat_aug_4, datetime(2009, 8, 29), True),
(offset_nem_sat_aug_4, datetime(2010, 8, 28), True),
(offset_nem_sat_aug_4, datetime(2011, 9, 3), True),
(offset_nem_sat_aug_4, datetime(2016, 9, 3), True),
(offset_nem_sat_aug_4, datetime(2017, 9, 2), True),
(offset_nem_sat_aug_4, datetime(2018, 9, 1), True),
(offset_nem_sat_aug_4, datetime(2019, 8, 31), True),
(offset_nem_sat_aug_4, datetime(2006, 8, 27), False),
(offset_nem_sat_aug_4, datetime(2007, 8, 28), False),
(offset_nem_sat_aug_4, datetime(2008, 8, 31), False),
(offset_nem_sat_aug_4, datetime(2009, 8, 30), False),
(offset_nem_sat_aug_4, datetime(2010, 8, 29), False),
(offset_nem_sat_aug_4, datetime(2011, 8, 28), False),
(offset_nem_sat_aug_4, datetime(2006, 8, 25), False),
(offset_nem_sat_aug_4, datetime(2007, 8, 24), False),
(offset_nem_sat_aug_4, datetime(2008, 8, 29), False),
(offset_nem_sat_aug_4, datetime(2009, 8, 28), False),
(offset_nem_sat_aug_4, datetime(2010, 8, 27), False),
(offset_nem_sat_aug_4, datetime(2011, 8, 26), False),
(offset_nem_sat_aug_4, datetime(2019, 8, 30), False),
# From Micron, see:
# http://google.brand.edgar-online.com/?sym=MU&formtypeID=7
(offset_nem_thu_aug_4, datetime(2012, 8, 30), True),
(offset_nem_thu_aug_4, datetime(2011, 9, 1), True),
# See: http://google.brand.edgar-online.com/?sym=MU&formtypeID=13
(offset_nem_thu_aug_4, datetime(2013, 5, 30), True),
(offset_nem_thu_aug_4, datetime(2013, 2, 28), True),
(offset_nem_thu_aug_4, datetime(2012, 11, 29), True),
(offset_nem_thu_aug_4, datetime(2012, 5, 31), True),
(offset_nem_thu_aug_4, datetime(2007, 3, 1), True),
(offset_nem_thu_aug_4, datetime(1994, 3, 3), True),
(offset_n, datetime(2012, 12, 31), False),
(offset_n, datetime(2013, 1, 1), True),
(offset_n, datetime(2013, 1, 2), False),
]
@pytest.mark.parametrize("case", on_offset_cases)
def test_onOffset(self, case):
offset, dt, expected = case
assert_onOffset(offset, dt, expected)
def test_offset(self):
offset = makeFY5253NearestEndMonthQuarter(
1, startingMonth=8, weekday=WeekDay.THU, qtr_with_extra_week=4
)
MU = [
datetime(2012, 5, 31),
datetime(2012, 8, 30),
datetime(2012, 11, 29),
datetime(2013, 2, 28),
datetime(2013, 5, 30),
]
date = MU[0] + relativedelta(days=-1)
for expected in MU:
assert_offset_equal(offset, date, expected)
date = date + offset
assert_offset_equal(offset, datetime(2012, 5, 31), datetime(2012, 8, 30))
assert_offset_equal(offset, datetime(2012, 5, 30), datetime(2012, 5, 31))
offset2 = FY5253Quarter(
weekday=5, startingMonth=12, variation="last", qtr_with_extra_week=4
)
assert_offset_equal(offset2, datetime(2013, 1, 15), datetime(2013, 3, 30))
def test_bunched_yearends():
# GH#14774 cases with two fiscal year-ends in the same calendar-year
fy = FY5253(n=1, weekday=5, startingMonth=12, variation="nearest")
dt = Timestamp("2004-01-01")
assert fy.rollback(dt) == Timestamp("2002-12-28")
assert (-fy).apply(dt) == Timestamp("2002-12-28")
assert dt - fy == Timestamp("2002-12-28")
assert fy.rollforward(dt) == Timestamp("2004-01-03")
assert fy.apply(dt) == Timestamp("2004-01-03")
assert fy + dt == Timestamp("2004-01-03")
assert dt + fy == Timestamp("2004-01-03")
# Same thing, but starting from a Timestamp in the previous year.
dt = Timestamp("2003-12-31")
assert fy.rollback(dt) == Timestamp("2002-12-28")
assert (-fy).apply(dt) == Timestamp("2002-12-28")
assert dt - fy == Timestamp("2002-12-28")
def test_fy5253_last_onoffset():
# GH#18877 dates on the year-end but not normalized to midnight
offset = FY5253(n=-5, startingMonth=5, variation="last", weekday=0)
ts = Timestamp("1984-05-28 06:29:43.955911354+0200", tz="Europe/San_Marino")
fast = offset.onOffset(ts)
slow = (ts + offset) - offset == ts
assert fast == slow
def test_fy5253_nearest_onoffset():
# GH#18877 dates on the year-end but not normalized to midnight
offset = FY5253(n=3, startingMonth=7, variation="nearest", weekday=2)
ts = Timestamp("2032-07-28 00:12:59.035729419+0000", tz="Africa/Dakar")
fast = offset.onOffset(ts)
slow = (ts + offset) - offset == ts
assert fast == slow
def test_fy5253qtr_onoffset_nearest():
# GH#19036
ts = Timestamp("1985-09-02 23:57:46.232550356-0300", tz="Atlantic/Bermuda")
offset = FY5253Quarter(
n=3, qtr_with_extra_week=1, startingMonth=2, variation="nearest", weekday=0
)
fast = offset.onOffset(ts)
slow = (ts + offset) - offset == ts
assert fast == slow
def test_fy5253qtr_onoffset_last():
# GH#19036
offset = FY5253Quarter(
n=-2, qtr_with_extra_week=1, startingMonth=7, variation="last", weekday=2
)
ts = Timestamp("2011-01-26 19:03:40.331096129+0200", tz="Africa/Windhoek")
slow = (ts + offset) - offset == ts
fast = offset.onOffset(ts)
assert fast == slow

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,139 @@
"""
Behavioral based tests for offsets and date_range.
This file is adapted from https://github.com/pandas-dev/pandas/pull/18761 -
which was more ambitious but less idiomatic in its use of Hypothesis.
You may wish to consult the previous version for inspiration on further
tests, or when trying to pin down the bugs exposed by the tests below.
"""
import warnings
from hypothesis import assume, given, strategies as st
from hypothesis.extra.dateutil import timezones as dateutil_timezones
from hypothesis.extra.pytz import timezones as pytz_timezones
import pytest
import pandas as pd
from pandas.tseries.offsets import (
BMonthBegin,
BMonthEnd,
BQuarterBegin,
BQuarterEnd,
BYearBegin,
BYearEnd,
MonthBegin,
MonthEnd,
QuarterBegin,
QuarterEnd,
YearBegin,
YearEnd,
)
# ----------------------------------------------------------------
# Helpers for generating random data
with warnings.catch_warnings():
warnings.simplefilter("ignore")
min_dt = (pd.Timestamp(1900, 1, 1).to_pydatetime(),)
max_dt = (pd.Timestamp(1900, 1, 1).to_pydatetime(),)
gen_date_range = st.builds(
pd.date_range,
start=st.datetimes(
# TODO: Choose the min/max values more systematically
min_value=pd.Timestamp(1900, 1, 1).to_pydatetime(),
max_value=pd.Timestamp(2100, 1, 1).to_pydatetime(),
),
periods=st.integers(min_value=2, max_value=100),
freq=st.sampled_from("Y Q M D H T s ms us ns".split()),
tz=st.one_of(st.none(), dateutil_timezones(), pytz_timezones()),
)
gen_random_datetime = st.datetimes(
min_value=min_dt,
max_value=max_dt,
timezones=st.one_of(st.none(), dateutil_timezones(), pytz_timezones()),
)
# The strategy for each type is registered in conftest.py, as they don't carry
# enough runtime information (e.g. type hints) to infer how to build them.
gen_yqm_offset = st.one_of(
*map(
st.from_type,
[
MonthBegin,
MonthEnd,
BMonthBegin,
BMonthEnd,
QuarterBegin,
QuarterEnd,
BQuarterBegin,
BQuarterEnd,
YearBegin,
YearEnd,
BYearBegin,
BYearEnd,
],
)
)
# ----------------------------------------------------------------
# Offset-specific behaviour tests
# Based on CI runs: Always passes on OSX, fails on Linux, sometimes on Windows
@pytest.mark.xfail(strict=False, reason="inconsistent between OSs, Pythons")
@given(gen_random_datetime, gen_yqm_offset)
def test_on_offset_implementations(dt, offset):
assume(not offset.normalize)
# check that the class-specific implementations of onOffset match
# the general case definition:
# (dt + offset) - offset == dt
compare = (dt + offset) - offset
assert offset.onOffset(dt) == (compare == dt)
@pytest.mark.xfail(
reason="res_v2 below is incorrect, needs to use the "
"commented-out version with tz_localize. "
"But with that fix in place, hypothesis then "
"has errors in timezone generation."
)
@given(gen_yqm_offset, gen_date_range)
def test_apply_index_implementations(offset, rng):
# offset.apply_index(dti)[i] should match dti[i] + offset
assume(offset.n != 0) # TODO: test for that case separately
# rng = pd.date_range(start='1/1/2000', periods=100000, freq='T')
ser = pd.Series(rng)
res = rng + offset
res_v2 = offset.apply_index(rng)
# res_v2 = offset.apply_index(rng.tz_localize(None)).tz_localize(rng.tz)
assert (res == res_v2).all()
assert res[0] == rng[0] + offset
assert res[-1] == rng[-1] + offset
res2 = ser + offset
# apply_index is only for indexes, not series, so no res2_v2
assert res2.iloc[0] == ser.iloc[0] + offset
assert res2.iloc[-1] == ser.iloc[-1] + offset
# TODO: Check randomly assorted entries, not just first/last
@pytest.mark.xfail # TODO: reason?
@given(gen_yqm_offset)
def test_shift_across_dst(offset):
# GH#18319 check that 1) timezone is correctly normalized and
# 2) that hour is not incorrectly changed by this normalization
# Note that dti includes a transition across DST boundary
dti = pd.date_range(
start="2017-10-30 12:00:00", end="2017-11-06", freq="D", tz="US/Eastern"
)
assert (dti.hour == 12).all() # we haven't screwed up yet
res = dti + offset
assert (res.hour == 12).all()

View File

@@ -0,0 +1,322 @@
"""
Tests for offsets.Tick and subclasses
"""
from datetime import datetime, timedelta
from hypothesis import assume, example, given, settings, strategies as st
import numpy as np
import pytest
from pandas import Timedelta, Timestamp
import pandas.util.testing as tm
from pandas.tseries import offsets
from pandas.tseries.offsets import Hour, Micro, Milli, Minute, Nano, Second
from .common import assert_offset_equal
# ---------------------------------------------------------------------
# Test Helpers
tick_classes = [Hour, Minute, Second, Milli, Micro, Nano]
# ---------------------------------------------------------------------
def test_apply_ticks():
result = offsets.Hour(3).apply(offsets.Hour(4))
exp = offsets.Hour(7)
assert result == exp
def test_delta_to_tick():
delta = timedelta(3)
tick = offsets._delta_to_tick(delta)
assert tick == offsets.Day(3)
td = Timedelta(nanoseconds=5)
tick = offsets._delta_to_tick(td)
assert tick == Nano(5)
@pytest.mark.parametrize("cls", tick_classes)
@settings(deadline=None) # GH 24641
@example(n=2, m=3)
@example(n=800, m=300)
@example(n=1000, m=5)
@given(n=st.integers(-999, 999), m=st.integers(-999, 999))
def test_tick_add_sub(cls, n, m):
# For all Tick subclasses and all integers n, m, we should have
# tick(n) + tick(m) == tick(n+m)
# tick(n) - tick(m) == tick(n-m)
left = cls(n)
right = cls(m)
expected = cls(n + m)
assert left + right == expected
assert left.apply(right) == expected
expected = cls(n - m)
assert left - right == expected
@pytest.mark.parametrize("cls", tick_classes)
@settings(deadline=None)
@example(n=2, m=3)
@given(n=st.integers(-999, 999), m=st.integers(-999, 999))
def test_tick_equality(cls, n, m):
assume(m != n)
# tick == tock iff tick.n == tock.n
left = cls(n)
right = cls(m)
assert left != right
assert not (left == right)
right = cls(n)
assert left == right
assert not (left != right)
if n != 0:
assert cls(n) != cls(-n)
# ---------------------------------------------------------------------
def test_Hour():
assert_offset_equal(Hour(), datetime(2010, 1, 1), datetime(2010, 1, 1, 1))
assert_offset_equal(Hour(-1), datetime(2010, 1, 1, 1), datetime(2010, 1, 1))
assert_offset_equal(2 * Hour(), datetime(2010, 1, 1), datetime(2010, 1, 1, 2))
assert_offset_equal(-1 * Hour(), datetime(2010, 1, 1, 1), datetime(2010, 1, 1))
assert Hour(3) + Hour(2) == Hour(5)
assert Hour(3) - Hour(2) == Hour()
assert Hour(4) != Hour(1)
def test_Minute():
assert_offset_equal(Minute(), datetime(2010, 1, 1), datetime(2010, 1, 1, 0, 1))
assert_offset_equal(Minute(-1), datetime(2010, 1, 1, 0, 1), datetime(2010, 1, 1))
assert_offset_equal(2 * Minute(), datetime(2010, 1, 1), datetime(2010, 1, 1, 0, 2))
assert_offset_equal(-1 * Minute(), datetime(2010, 1, 1, 0, 1), datetime(2010, 1, 1))
assert Minute(3) + Minute(2) == Minute(5)
assert Minute(3) - Minute(2) == Minute()
assert Minute(5) != Minute()
def test_Second():
assert_offset_equal(Second(), datetime(2010, 1, 1), datetime(2010, 1, 1, 0, 0, 1))
assert_offset_equal(Second(-1), datetime(2010, 1, 1, 0, 0, 1), datetime(2010, 1, 1))
assert_offset_equal(
2 * Second(), datetime(2010, 1, 1), datetime(2010, 1, 1, 0, 0, 2)
)
assert_offset_equal(
-1 * Second(), datetime(2010, 1, 1, 0, 0, 1), datetime(2010, 1, 1)
)
assert Second(3) + Second(2) == Second(5)
assert Second(3) - Second(2) == Second()
def test_Millisecond():
assert_offset_equal(
Milli(), datetime(2010, 1, 1), datetime(2010, 1, 1, 0, 0, 0, 1000)
)
assert_offset_equal(
Milli(-1), datetime(2010, 1, 1, 0, 0, 0, 1000), datetime(2010, 1, 1)
)
assert_offset_equal(
Milli(2), datetime(2010, 1, 1), datetime(2010, 1, 1, 0, 0, 0, 2000)
)
assert_offset_equal(
2 * Milli(), datetime(2010, 1, 1), datetime(2010, 1, 1, 0, 0, 0, 2000)
)
assert_offset_equal(
-1 * Milli(), datetime(2010, 1, 1, 0, 0, 0, 1000), datetime(2010, 1, 1)
)
assert Milli(3) + Milli(2) == Milli(5)
assert Milli(3) - Milli(2) == Milli()
def test_MillisecondTimestampArithmetic():
assert_offset_equal(
Milli(), Timestamp("2010-01-01"), Timestamp("2010-01-01 00:00:00.001")
)
assert_offset_equal(
Milli(-1), Timestamp("2010-01-01 00:00:00.001"), Timestamp("2010-01-01")
)
def test_Microsecond():
assert_offset_equal(Micro(), datetime(2010, 1, 1), datetime(2010, 1, 1, 0, 0, 0, 1))
assert_offset_equal(
Micro(-1), datetime(2010, 1, 1, 0, 0, 0, 1), datetime(2010, 1, 1)
)
assert_offset_equal(
2 * Micro(), datetime(2010, 1, 1), datetime(2010, 1, 1, 0, 0, 0, 2)
)
assert_offset_equal(
-1 * Micro(), datetime(2010, 1, 1, 0, 0, 0, 1), datetime(2010, 1, 1)
)
assert Micro(3) + Micro(2) == Micro(5)
assert Micro(3) - Micro(2) == Micro()
def test_NanosecondGeneric():
timestamp = Timestamp(datetime(2010, 1, 1))
assert timestamp.nanosecond == 0
result = timestamp + Nano(10)
assert result.nanosecond == 10
reverse_result = Nano(10) + timestamp
assert reverse_result.nanosecond == 10
def test_Nanosecond():
timestamp = Timestamp(datetime(2010, 1, 1))
assert_offset_equal(Nano(), timestamp, timestamp + np.timedelta64(1, "ns"))
assert_offset_equal(Nano(-1), timestamp + np.timedelta64(1, "ns"), timestamp)
assert_offset_equal(2 * Nano(), timestamp, timestamp + np.timedelta64(2, "ns"))
assert_offset_equal(-1 * Nano(), timestamp + np.timedelta64(1, "ns"), timestamp)
assert Nano(3) + Nano(2) == Nano(5)
assert Nano(3) - Nano(2) == Nano()
# GH9284
assert Nano(1) + Nano(10) == Nano(11)
assert Nano(5) + Micro(1) == Nano(1005)
assert Micro(5) + Nano(1) == Nano(5001)
@pytest.mark.parametrize(
"kls, expected",
[
(Hour, Timedelta(hours=5)),
(Minute, Timedelta(hours=2, minutes=3)),
(Second, Timedelta(hours=2, seconds=3)),
(Milli, Timedelta(hours=2, milliseconds=3)),
(Micro, Timedelta(hours=2, microseconds=3)),
(Nano, Timedelta(hours=2, nanoseconds=3)),
],
)
def test_tick_addition(kls, expected):
offset = kls(3)
result = offset + Timedelta(hours=2)
assert isinstance(result, Timedelta)
assert result == expected
@pytest.mark.parametrize("cls", tick_classes)
def test_tick_division(cls):
off = cls(10)
assert off / cls(5) == 2
assert off / 2 == cls(5)
assert off / 2.0 == cls(5)
assert off / off.delta == 1
assert off / off.delta.to_timedelta64() == 1
assert off / Nano(1) == off.delta / Nano(1).delta
if cls is not Nano:
# A case where we end up with a smaller class
result = off / 1000
assert isinstance(result, offsets.Tick)
assert not isinstance(result, cls)
assert result.delta == off.delta / 1000
if cls._inc < Timedelta(seconds=1):
# Case where we end up with a bigger class
result = off / 0.001
assert isinstance(result, offsets.Tick)
assert not isinstance(result, cls)
assert result.delta == off.delta / 0.001
@pytest.mark.parametrize("cls", tick_classes)
def test_tick_rdiv(cls):
off = cls(10)
delta = off.delta
td64 = delta.to_timedelta64()
with pytest.raises(TypeError):
2 / off
with pytest.raises(TypeError):
2.0 / off
assert (td64 * 2.5) / off == 2.5
if cls is not Nano:
# skip pytimedelta for Nano since it gets dropped
assert (delta.to_pytimedelta() * 2) / off == 2
result = np.array([2 * td64, td64]) / off
expected = np.array([2.0, 1.0])
tm.assert_numpy_array_equal(result, expected)
@pytest.mark.parametrize("cls1", tick_classes)
@pytest.mark.parametrize("cls2", tick_classes)
def test_tick_zero(cls1, cls2):
assert cls1(0) == cls2(0)
assert cls1(0) + cls2(0) == cls1(0)
if cls1 is not Nano:
assert cls1(2) + cls2(0) == cls1(2)
if cls1 is Nano:
assert cls1(2) + Nano(0) == cls1(2)
@pytest.mark.parametrize("cls", tick_classes)
def test_tick_equalities(cls):
assert cls() == cls(1)
@pytest.mark.parametrize("cls", tick_classes)
def test_tick_offset(cls):
assert not cls().isAnchored()
@pytest.mark.parametrize("cls", tick_classes)
def test_compare_ticks(cls):
three = cls(3)
four = cls(4)
assert three < cls(4)
assert cls(3) < four
assert four > cls(3)
assert cls(4) > three
assert cls(3) == cls(3)
assert cls(3) != cls(4)
@pytest.mark.parametrize("cls", tick_classes)
def test_compare_ticks_to_strs(cls):
# GH#23524
off = cls(19)
# These tests should work with any strings, but we particularly are
# interested in "infer" as that comparison is convenient to make in
# Datetime/Timedelta Array/Index constructors
assert not off == "infer"
assert not "foo" == off
for left, right in [("infer", off), (off, "infer")]:
with pytest.raises(TypeError):
left < right
with pytest.raises(TypeError):
left <= right
with pytest.raises(TypeError):
left > right
with pytest.raises(TypeError):
left >= right

File diff suppressed because it is too large Load Diff