demo + utils venv
This commit is contained in:
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
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: %s\nActual: %s\nFor Offset: %s)"
|
||||
"\nAt Date: %s" %
|
||||
(expected, actual, offset, base))
|
||||
|
||||
|
||||
def assert_onOffset(offset, date, expected):
|
||||
actual = offset.onOffset(date)
|
||||
assert actual == expected, ("\nExpected: %s\nActual: %s\nFor Offset: %s)"
|
||||
"\nAt Date: %s" %
|
||||
(expected, actual, offset, date))
|
||||
@@ -0,0 +1,21 @@
|
||||
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
|
||||
@@ -0,0 +1,657 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
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 %r to yield %r (actual: %r)" %
|
||||
(name, expected, 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
+108
@@ -0,0 +1,108 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
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
|
||||
@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)
|
||||
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
|
||||
@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()
|
||||
@@ -0,0 +1,320 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Tests for offsets.Tick and subclasses
|
||||
"""
|
||||
from __future__ import division
|
||||
|
||||
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
|
||||
|
||||
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 / .001
|
||||
assert isinstance(result, offsets.Tick)
|
||||
assert not isinstance(result, cls)
|
||||
assert result.delta == off.delta / .001
|
||||
|
||||
|
||||
@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
|
||||
+1027
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,793 @@
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from pandas._libs.tslibs import frequencies as libfrequencies, resolution
|
||||
from pandas._libs.tslibs.ccalendar import MONTHS
|
||||
from pandas._libs.tslibs.frequencies import (
|
||||
INVALID_FREQ_ERR_MSG, FreqGroup, _period_code_map, get_freq, get_freq_code)
|
||||
import pandas.compat as compat
|
||||
from pandas.compat import is_platform_windows, range
|
||||
|
||||
from pandas import (
|
||||
DatetimeIndex, Index, Series, Timedelta, 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
|
||||
|
||||
|
||||
class TestToOffset(object):
|
||||
|
||||
def test_to_offset_multiple(self):
|
||||
freqstr = '2h30min'
|
||||
freqstr2 = '2h 30min'
|
||||
|
||||
result = frequencies.to_offset(freqstr)
|
||||
assert (result == frequencies.to_offset(freqstr2))
|
||||
expected = offsets.Minute(150)
|
||||
assert (result == expected)
|
||||
|
||||
freqstr = '2h30min15s'
|
||||
result = frequencies.to_offset(freqstr)
|
||||
expected = offsets.Second(150 * 60 + 15)
|
||||
assert (result == expected)
|
||||
|
||||
freqstr = '2h 60min'
|
||||
result = frequencies.to_offset(freqstr)
|
||||
expected = offsets.Hour(3)
|
||||
assert (result == expected)
|
||||
|
||||
freqstr = '2h 20.5min'
|
||||
result = frequencies.to_offset(freqstr)
|
||||
expected = offsets.Second(8430)
|
||||
assert (result == expected)
|
||||
|
||||
freqstr = '1.5min'
|
||||
result = frequencies.to_offset(freqstr)
|
||||
expected = offsets.Second(90)
|
||||
assert (result == expected)
|
||||
|
||||
freqstr = '0.5S'
|
||||
result = frequencies.to_offset(freqstr)
|
||||
expected = offsets.Milli(500)
|
||||
assert (result == expected)
|
||||
|
||||
freqstr = '15l500u'
|
||||
result = frequencies.to_offset(freqstr)
|
||||
expected = offsets.Micro(15500)
|
||||
assert (result == expected)
|
||||
|
||||
freqstr = '10s75L'
|
||||
result = frequencies.to_offset(freqstr)
|
||||
expected = offsets.Milli(10075)
|
||||
assert (result == expected)
|
||||
|
||||
freqstr = '1s0.25ms'
|
||||
result = frequencies.to_offset(freqstr)
|
||||
expected = offsets.Micro(1000250)
|
||||
assert (result == expected)
|
||||
|
||||
freqstr = '1s0.25L'
|
||||
result = frequencies.to_offset(freqstr)
|
||||
expected = offsets.Micro(1000250)
|
||||
assert (result == expected)
|
||||
|
||||
freqstr = '2800N'
|
||||
result = frequencies.to_offset(freqstr)
|
||||
expected = offsets.Nano(2800)
|
||||
assert (result == expected)
|
||||
|
||||
freqstr = '2SM'
|
||||
result = frequencies.to_offset(freqstr)
|
||||
expected = offsets.SemiMonthEnd(2)
|
||||
assert (result == expected)
|
||||
|
||||
freqstr = '2SM-16'
|
||||
result = frequencies.to_offset(freqstr)
|
||||
expected = offsets.SemiMonthEnd(2, day_of_month=16)
|
||||
assert (result == expected)
|
||||
|
||||
freqstr = '2SMS-14'
|
||||
result = frequencies.to_offset(freqstr)
|
||||
expected = offsets.SemiMonthBegin(2, day_of_month=14)
|
||||
assert (result == expected)
|
||||
|
||||
freqstr = '2SMS-15'
|
||||
result = frequencies.to_offset(freqstr)
|
||||
expected = offsets.SemiMonthBegin(2)
|
||||
assert (result == expected)
|
||||
|
||||
# malformed
|
||||
with pytest.raises(ValueError, match='Invalid frequency: 2h20m'):
|
||||
frequencies.to_offset('2h20m')
|
||||
|
||||
def test_to_offset_negative(self):
|
||||
freqstr = '-1S'
|
||||
result = frequencies.to_offset(freqstr)
|
||||
assert (result.n == -1)
|
||||
|
||||
freqstr = '-5min10s'
|
||||
result = frequencies.to_offset(freqstr)
|
||||
assert (result.n == -310)
|
||||
|
||||
freqstr = '-2SM'
|
||||
result = frequencies.to_offset(freqstr)
|
||||
assert (result.n == -2)
|
||||
|
||||
freqstr = '-1SMS'
|
||||
result = frequencies.to_offset(freqstr)
|
||||
assert (result.n == -1)
|
||||
|
||||
def test_to_offset_invalid(self):
|
||||
# GH 13930
|
||||
with pytest.raises(ValueError, match='Invalid frequency: U1'):
|
||||
frequencies.to_offset('U1')
|
||||
with pytest.raises(ValueError, match='Invalid frequency: -U'):
|
||||
frequencies.to_offset('-U')
|
||||
with pytest.raises(ValueError, match='Invalid frequency: 3U1'):
|
||||
frequencies.to_offset('3U1')
|
||||
with pytest.raises(ValueError, match='Invalid frequency: -2-3U'):
|
||||
frequencies.to_offset('-2-3U')
|
||||
with pytest.raises(ValueError, match='Invalid frequency: -2D:3H'):
|
||||
frequencies.to_offset('-2D:3H')
|
||||
with pytest.raises(ValueError, match='Invalid frequency: 1.5.0S'):
|
||||
frequencies.to_offset('1.5.0S')
|
||||
|
||||
# split offsets with spaces are valid
|
||||
assert frequencies.to_offset('2D 3H') == offsets.Hour(51)
|
||||
assert frequencies.to_offset('2 D3 H') == offsets.Hour(51)
|
||||
assert frequencies.to_offset('2 D 3 H') == offsets.Hour(51)
|
||||
assert frequencies.to_offset(' 2 D 3 H ') == offsets.Hour(51)
|
||||
assert frequencies.to_offset(' H ') == offsets.Hour()
|
||||
assert frequencies.to_offset(' 3 H ') == offsets.Hour(3)
|
||||
|
||||
# special cases
|
||||
assert frequencies.to_offset('2SMS-15') == offsets.SemiMonthBegin(2)
|
||||
with pytest.raises(ValueError, match='Invalid frequency: 2SMS-15-15'):
|
||||
frequencies.to_offset('2SMS-15-15')
|
||||
with pytest.raises(ValueError, match='Invalid frequency: 2SMS-15D'):
|
||||
frequencies.to_offset('2SMS-15D')
|
||||
|
||||
def test_to_offset_leading_zero(self):
|
||||
freqstr = '00H 00T 01S'
|
||||
result = frequencies.to_offset(freqstr)
|
||||
assert (result.n == 1)
|
||||
|
||||
freqstr = '-00H 03T 14S'
|
||||
result = frequencies.to_offset(freqstr)
|
||||
assert (result.n == -194)
|
||||
|
||||
def test_to_offset_leading_plus(self):
|
||||
freqstr = '+1d'
|
||||
result = frequencies.to_offset(freqstr)
|
||||
assert (result.n == 1)
|
||||
|
||||
freqstr = '+2h30min'
|
||||
result = frequencies.to_offset(freqstr)
|
||||
assert (result.n == 150)
|
||||
|
||||
for bad_freq in ['+-1d', '-+1h', '+1', '-7', '+d', '-m']:
|
||||
with pytest.raises(ValueError, match='Invalid frequency:'):
|
||||
frequencies.to_offset(bad_freq)
|
||||
|
||||
def test_to_offset_pd_timedelta(self):
|
||||
# Tests for #9064
|
||||
td = Timedelta(days=1, seconds=1)
|
||||
result = frequencies.to_offset(td)
|
||||
expected = offsets.Second(86401)
|
||||
assert (expected == result)
|
||||
|
||||
td = Timedelta(days=-1, seconds=1)
|
||||
result = frequencies.to_offset(td)
|
||||
expected = offsets.Second(-86399)
|
||||
assert (expected == result)
|
||||
|
||||
td = Timedelta(hours=1, minutes=10)
|
||||
result = frequencies.to_offset(td)
|
||||
expected = offsets.Minute(70)
|
||||
assert (expected == result)
|
||||
|
||||
td = Timedelta(hours=1, minutes=-10)
|
||||
result = frequencies.to_offset(td)
|
||||
expected = offsets.Minute(50)
|
||||
assert (expected == result)
|
||||
|
||||
td = Timedelta(weeks=1)
|
||||
result = frequencies.to_offset(td)
|
||||
expected = offsets.Day(7)
|
||||
assert (expected == result)
|
||||
|
||||
td1 = Timedelta(hours=1)
|
||||
result1 = frequencies.to_offset(td1)
|
||||
result2 = frequencies.to_offset('60min')
|
||||
assert (result1 == result2)
|
||||
|
||||
td = Timedelta(microseconds=1)
|
||||
result = frequencies.to_offset(td)
|
||||
expected = offsets.Micro(1)
|
||||
assert (expected == result)
|
||||
|
||||
td = Timedelta(microseconds=0)
|
||||
pytest.raises(ValueError, lambda: frequencies.to_offset(td))
|
||||
|
||||
def test_anchored_shortcuts(self):
|
||||
result = frequencies.to_offset('W')
|
||||
expected = frequencies.to_offset('W-SUN')
|
||||
assert (result == expected)
|
||||
|
||||
result1 = frequencies.to_offset('Q')
|
||||
result2 = frequencies.to_offset('Q-DEC')
|
||||
expected = offsets.QuarterEnd(startingMonth=12)
|
||||
assert (result1 == expected)
|
||||
assert (result2 == expected)
|
||||
|
||||
result1 = frequencies.to_offset('Q-MAY')
|
||||
expected = offsets.QuarterEnd(startingMonth=5)
|
||||
assert (result1 == expected)
|
||||
|
||||
result1 = frequencies.to_offset('SM')
|
||||
result2 = frequencies.to_offset('SM-15')
|
||||
expected = offsets.SemiMonthEnd(day_of_month=15)
|
||||
assert (result1 == expected)
|
||||
assert (result2 == expected)
|
||||
|
||||
result = frequencies.to_offset('SM-1')
|
||||
expected = offsets.SemiMonthEnd(day_of_month=1)
|
||||
assert (result == expected)
|
||||
|
||||
result = frequencies.to_offset('SM-27')
|
||||
expected = offsets.SemiMonthEnd(day_of_month=27)
|
||||
assert (result == expected)
|
||||
|
||||
result = frequencies.to_offset('SMS-2')
|
||||
expected = offsets.SemiMonthBegin(day_of_month=2)
|
||||
assert (result == expected)
|
||||
|
||||
result = frequencies.to_offset('SMS-27')
|
||||
expected = offsets.SemiMonthBegin(day_of_month=27)
|
||||
assert (result == expected)
|
||||
|
||||
# ensure invalid cases fail as expected
|
||||
invalid_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']
|
||||
for invalid_anchor in invalid_anchors:
|
||||
with pytest.raises(ValueError, match='Invalid frequency: '):
|
||||
frequencies.to_offset(invalid_anchor)
|
||||
|
||||
|
||||
def test_ms_vs_MS():
|
||||
left = frequencies.get_offset('ms')
|
||||
right = frequencies.get_offset('MS')
|
||||
assert left == offsets.Milli()
|
||||
assert right == offsets.MonthBegin()
|
||||
|
||||
|
||||
def test_rule_aliases():
|
||||
rule = frequencies.to_offset('10us')
|
||||
assert rule == offsets.Micro(10)
|
||||
|
||||
|
||||
class TestFrequencyCode(object):
|
||||
|
||||
def test_freq_code(self):
|
||||
assert get_freq('A') == 1000
|
||||
assert get_freq('3A') == 1000
|
||||
assert get_freq('-1A') == 1000
|
||||
|
||||
assert get_freq('Y') == 1000
|
||||
assert get_freq('3Y') == 1000
|
||||
assert get_freq('-1Y') == 1000
|
||||
|
||||
assert get_freq('W') == 4000
|
||||
assert get_freq('W-MON') == 4001
|
||||
assert get_freq('W-FRI') == 4005
|
||||
|
||||
for freqstr, code in compat.iteritems(_period_code_map):
|
||||
result = get_freq(freqstr)
|
||||
assert result == code
|
||||
|
||||
result = resolution.get_freq_group(freqstr)
|
||||
assert result == code // 1000 * 1000
|
||||
|
||||
result = resolution.get_freq_group(code)
|
||||
assert result == code // 1000 * 1000
|
||||
|
||||
def test_freq_group(self):
|
||||
assert resolution.get_freq_group('A') == 1000
|
||||
assert resolution.get_freq_group('3A') == 1000
|
||||
assert resolution.get_freq_group('-1A') == 1000
|
||||
assert resolution.get_freq_group('A-JAN') == 1000
|
||||
assert resolution.get_freq_group('A-MAY') == 1000
|
||||
|
||||
assert resolution.get_freq_group('Y') == 1000
|
||||
assert resolution.get_freq_group('3Y') == 1000
|
||||
assert resolution.get_freq_group('-1Y') == 1000
|
||||
assert resolution.get_freq_group('Y-JAN') == 1000
|
||||
assert resolution.get_freq_group('Y-MAY') == 1000
|
||||
|
||||
assert resolution.get_freq_group(offsets.YearEnd()) == 1000
|
||||
assert resolution.get_freq_group(offsets.YearEnd(month=1)) == 1000
|
||||
assert resolution.get_freq_group(offsets.YearEnd(month=5)) == 1000
|
||||
|
||||
assert resolution.get_freq_group('W') == 4000
|
||||
assert resolution.get_freq_group('W-MON') == 4000
|
||||
assert resolution.get_freq_group('W-FRI') == 4000
|
||||
assert resolution.get_freq_group(offsets.Week()) == 4000
|
||||
assert resolution.get_freq_group(offsets.Week(weekday=1)) == 4000
|
||||
assert resolution.get_freq_group(offsets.Week(weekday=5)) == 4000
|
||||
|
||||
def test_get_to_timestamp_base(self):
|
||||
tsb = libfrequencies.get_to_timestamp_base
|
||||
|
||||
assert (tsb(get_freq_code('D')[0]) ==
|
||||
get_freq_code('D')[0])
|
||||
assert (tsb(get_freq_code('W')[0]) ==
|
||||
get_freq_code('D')[0])
|
||||
assert (tsb(get_freq_code('M')[0]) ==
|
||||
get_freq_code('D')[0])
|
||||
|
||||
assert (tsb(get_freq_code('S')[0]) ==
|
||||
get_freq_code('S')[0])
|
||||
assert (tsb(get_freq_code('T')[0]) ==
|
||||
get_freq_code('S')[0])
|
||||
assert (tsb(get_freq_code('H')[0]) ==
|
||||
get_freq_code('S')[0])
|
||||
|
||||
def test_freq_to_reso(self):
|
||||
Reso = resolution.Resolution
|
||||
|
||||
assert Reso.get_str_from_freq('A') == 'year'
|
||||
assert Reso.get_str_from_freq('Q') == 'quarter'
|
||||
assert Reso.get_str_from_freq('M') == 'month'
|
||||
assert Reso.get_str_from_freq('D') == 'day'
|
||||
assert Reso.get_str_from_freq('H') == 'hour'
|
||||
assert Reso.get_str_from_freq('T') == 'minute'
|
||||
assert Reso.get_str_from_freq('S') == 'second'
|
||||
assert Reso.get_str_from_freq('L') == 'millisecond'
|
||||
assert Reso.get_str_from_freq('U') == 'microsecond'
|
||||
assert Reso.get_str_from_freq('N') == 'nanosecond'
|
||||
|
||||
for freq in ['A', 'Q', 'M', 'D', 'H', 'T', 'S', 'L', 'U', 'N']:
|
||||
# check roundtrip
|
||||
result = Reso.get_freq(Reso.get_str_from_freq(freq))
|
||||
assert freq == result
|
||||
|
||||
for freq in ['D', 'H', 'T', 'S', 'L', 'U']:
|
||||
result = Reso.get_freq(Reso.get_str(Reso.get_reso_from_freq(freq)))
|
||||
assert freq == result
|
||||
|
||||
def test_resolution_bumping(self):
|
||||
# see gh-14378
|
||||
Reso = resolution.Resolution
|
||||
|
||||
assert Reso.get_stride_from_decimal(1.5, 'T') == (90, 'S')
|
||||
assert Reso.get_stride_from_decimal(62.4, 'T') == (3744, 'S')
|
||||
assert Reso.get_stride_from_decimal(1.04, 'H') == (3744, 'S')
|
||||
assert Reso.get_stride_from_decimal(1, 'D') == (1, 'D')
|
||||
assert (Reso.get_stride_from_decimal(0.342931, 'H') ==
|
||||
(1234551600, 'U'))
|
||||
assert Reso.get_stride_from_decimal(1.2345, 'D') == (106660800, 'L')
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
Reso.get_stride_from_decimal(0.5, 'N')
|
||||
|
||||
# too much precision in the input can prevent
|
||||
with pytest.raises(ValueError):
|
||||
Reso.get_stride_from_decimal(0.3429324798798269273987982, 'H')
|
||||
|
||||
def test_get_freq_code(self):
|
||||
# frequency str
|
||||
assert (get_freq_code('A') ==
|
||||
(get_freq('A'), 1))
|
||||
assert (get_freq_code('3D') ==
|
||||
(get_freq('D'), 3))
|
||||
assert (get_freq_code('-2M') ==
|
||||
(get_freq('M'), -2))
|
||||
|
||||
# tuple
|
||||
assert (get_freq_code(('D', 1)) ==
|
||||
(get_freq('D'), 1))
|
||||
assert (get_freq_code(('A', 3)) ==
|
||||
(get_freq('A'), 3))
|
||||
assert (get_freq_code(('M', -2)) ==
|
||||
(get_freq('M'), -2))
|
||||
|
||||
# numeric tuple
|
||||
assert get_freq_code((1000, 1)) == (1000, 1)
|
||||
|
||||
# offsets
|
||||
assert (get_freq_code(offsets.Day()) ==
|
||||
(get_freq('D'), 1))
|
||||
assert (get_freq_code(offsets.Day(3)) ==
|
||||
(get_freq('D'), 3))
|
||||
assert (get_freq_code(offsets.Day(-2)) ==
|
||||
(get_freq('D'), -2))
|
||||
|
||||
assert (get_freq_code(offsets.MonthEnd()) ==
|
||||
(get_freq('M'), 1))
|
||||
assert (get_freq_code(offsets.MonthEnd(3)) ==
|
||||
(get_freq('M'), 3))
|
||||
assert (get_freq_code(offsets.MonthEnd(-2)) ==
|
||||
(get_freq('M'), -2))
|
||||
|
||||
assert (get_freq_code(offsets.Week()) ==
|
||||
(get_freq('W'), 1))
|
||||
assert (get_freq_code(offsets.Week(3)) ==
|
||||
(get_freq('W'), 3))
|
||||
assert (get_freq_code(offsets.Week(-2)) ==
|
||||
(get_freq('W'), -2))
|
||||
|
||||
# Monday is weekday=0
|
||||
assert (get_freq_code(offsets.Week(weekday=1)) ==
|
||||
(get_freq('W-TUE'), 1))
|
||||
assert (get_freq_code(offsets.Week(3, weekday=0)) ==
|
||||
(get_freq('W-MON'), 3))
|
||||
assert (get_freq_code(offsets.Week(-2, weekday=4)) ==
|
||||
(get_freq('W-FRI'), -2))
|
||||
|
||||
def test_frequency_misc(self):
|
||||
assert (resolution.get_freq_group('T') ==
|
||||
FreqGroup.FR_MIN)
|
||||
|
||||
code, stride = get_freq_code(offsets.Hour())
|
||||
assert code == FreqGroup.FR_HR
|
||||
|
||||
code, stride = get_freq_code((5, 'T'))
|
||||
assert code == FreqGroup.FR_MIN
|
||||
assert stride == 5
|
||||
|
||||
offset = offsets.Hour()
|
||||
result = frequencies.to_offset(offset)
|
||||
assert result == offset
|
||||
|
||||
result = frequencies.to_offset((5, 'T'))
|
||||
expected = offsets.Minute(5)
|
||||
assert result == expected
|
||||
|
||||
with pytest.raises(ValueError, match='Invalid frequency'):
|
||||
get_freq_code((5, 'baz'))
|
||||
|
||||
with pytest.raises(ValueError, match='Invalid frequency'):
|
||||
frequencies.to_offset('100foo')
|
||||
|
||||
with pytest.raises(ValueError, match='Could not evaluate'):
|
||||
frequencies.to_offset(('', ''))
|
||||
|
||||
|
||||
_dti = DatetimeIndex
|
||||
|
||||
|
||||
class TestFrequencyInference(object):
|
||||
|
||||
def test_raise_if_period_index(self):
|
||||
index = period_range(start="1/1/1990", periods=20, freq="M")
|
||||
pytest.raises(TypeError, frequencies.infer_freq, index)
|
||||
|
||||
def test_raise_if_too_few(self):
|
||||
index = _dti(['12/31/1998', '1/3/1999'])
|
||||
pytest.raises(ValueError, frequencies.infer_freq, index)
|
||||
|
||||
def test_business_daily(self):
|
||||
index = _dti(['01/01/1999', '1/4/1999', '1/5/1999'])
|
||||
assert frequencies.infer_freq(index) == 'B'
|
||||
|
||||
def test_business_daily_look_alike(self):
|
||||
# GH 16624, do not infer 'B' when 'weekend' (2-day gap) in wrong place
|
||||
index = _dti(['12/31/1998', '1/3/1999', '1/4/1999'])
|
||||
assert frequencies.infer_freq(index) is None
|
||||
|
||||
def test_day(self):
|
||||
self._check_tick(timedelta(1), 'D')
|
||||
|
||||
def test_day_corner(self):
|
||||
index = _dti(['1/1/2000', '1/2/2000', '1/3/2000'])
|
||||
assert frequencies.infer_freq(index) == 'D'
|
||||
|
||||
def test_non_datetimeindex(self):
|
||||
dates = to_datetime(['1/1/2000', '1/2/2000', '1/3/2000'])
|
||||
assert frequencies.infer_freq(dates) == 'D'
|
||||
|
||||
def test_hour(self):
|
||||
self._check_tick(timedelta(hours=1), 'H')
|
||||
|
||||
def test_minute(self):
|
||||
self._check_tick(timedelta(minutes=1), 'T')
|
||||
|
||||
def test_second(self):
|
||||
self._check_tick(timedelta(seconds=1), 'S')
|
||||
|
||||
def test_millisecond(self):
|
||||
self._check_tick(timedelta(microseconds=1000), 'L')
|
||||
|
||||
def test_microsecond(self):
|
||||
self._check_tick(timedelta(microseconds=1), 'U')
|
||||
|
||||
def test_nanosecond(self):
|
||||
self._check_tick(np.timedelta64(1, 'ns'), 'N')
|
||||
|
||||
def _check_tick(self, base_delta, code):
|
||||
b = Timestamp(datetime.now())
|
||||
for i in range(1, 5):
|
||||
inc = base_delta * i
|
||||
index = _dti([b + inc * j for j in range(3)])
|
||||
if i > 1:
|
||||
exp_freq = '%d%s' % (i, code)
|
||||
else:
|
||||
exp_freq = code
|
||||
assert frequencies.infer_freq(index) == exp_freq
|
||||
|
||||
index = _dti([b + base_delta * 7] + [b + base_delta * j for j in range(
|
||||
3)])
|
||||
assert frequencies.infer_freq(index) is None
|
||||
|
||||
index = _dti([b + base_delta * j for j in range(3)] + [b + base_delta *
|
||||
7])
|
||||
|
||||
assert frequencies.infer_freq(index) is None
|
||||
|
||||
def test_weekly(self):
|
||||
days = ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN']
|
||||
|
||||
for day in days:
|
||||
self._check_generated_range('1/1/2000', 'W-%s' % day)
|
||||
|
||||
def test_week_of_month(self):
|
||||
days = ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN']
|
||||
|
||||
for day in days:
|
||||
for i in range(1, 5):
|
||||
self._check_generated_range('1/1/2000', 'WOM-%d%s' % (i, day))
|
||||
|
||||
def test_fifth_week_of_month(self):
|
||||
# Only supports freq up to WOM-4. See #9425
|
||||
func = lambda: date_range('2014-01-01', freq='WOM-5MON')
|
||||
pytest.raises(ValueError, func)
|
||||
|
||||
def test_fifth_week_of_month_infer(self):
|
||||
# Only attempts to infer up to WOM-4. See #9425
|
||||
index = DatetimeIndex(["2014-03-31", "2014-06-30", "2015-03-30"])
|
||||
assert frequencies.infer_freq(index) is None
|
||||
|
||||
def test_week_of_month_fake(self):
|
||||
# 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_monthly(self):
|
||||
self._check_generated_range('1/1/2000', 'M')
|
||||
|
||||
def test_monthly_ambiguous(self):
|
||||
rng = _dti(['1/31/2000', '2/29/2000', '3/31/2000'])
|
||||
assert rng.inferred_freq == 'M'
|
||||
|
||||
def test_business_monthly(self):
|
||||
self._check_generated_range('1/1/2000', 'BM')
|
||||
|
||||
def test_business_start_monthly(self):
|
||||
self._check_generated_range('1/1/2000', 'BMS')
|
||||
|
||||
def test_quarterly(self):
|
||||
for month in ['JAN', 'FEB', 'MAR']:
|
||||
self._check_generated_range('1/1/2000', 'Q-%s' % month)
|
||||
|
||||
def test_annual(self):
|
||||
for month in MONTHS:
|
||||
self._check_generated_range('1/1/2000', 'A-%s' % month)
|
||||
|
||||
def test_business_annual(self):
|
||||
for month in MONTHS:
|
||||
self._check_generated_range('1/1/2000', 'BA-%s' % month)
|
||||
|
||||
def test_annual_ambiguous(self):
|
||||
rng = _dti(['1/31/2000', '1/31/2001', '1/31/2002'])
|
||||
assert rng.inferred_freq == 'A-JAN'
|
||||
|
||||
def _check_generated_range(self, start, freq):
|
||||
freq = freq.upper()
|
||||
|
||||
gen = date_range(start, periods=7, freq=freq)
|
||||
index = _dti(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
|
||||
|
||||
gen = date_range(start, periods=5, freq=freq)
|
||||
index = _dti(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
|
||||
|
||||
def test_infer_freq(self):
|
||||
rng = period_range('1959Q2', '2009Q3', freq='Q')
|
||||
rng = Index(rng.to_timestamp('D', how='e').astype(object))
|
||||
assert rng.inferred_freq == 'Q-DEC'
|
||||
|
||||
rng = period_range('1959Q2', '2009Q3', freq='Q-NOV')
|
||||
rng = Index(rng.to_timestamp('D', how='e').astype(object))
|
||||
assert rng.inferred_freq == 'Q-NOV'
|
||||
|
||||
rng = period_range('1959Q2', '2009Q3', freq='Q-OCT')
|
||||
rng = Index(rng.to_timestamp('D', how='e').astype(object))
|
||||
assert rng.inferred_freq == 'Q-OCT'
|
||||
|
||||
def test_infer_freq_tz(self):
|
||||
|
||||
freqs = {'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']}
|
||||
|
||||
# GH 7310
|
||||
for tz in [None, 'Australia/Sydney', 'Asia/Tokyo', 'Europe/Paris',
|
||||
'US/Pacific', 'US/Eastern']:
|
||||
for expected, dates in compat.iteritems(freqs):
|
||||
idx = DatetimeIndex(dates, tz=tz)
|
||||
assert idx.inferred_freq == expected
|
||||
|
||||
def test_infer_freq_tz_transition(self):
|
||||
# Tests for #8772
|
||||
date_pairs = [['2013-11-02', '2013-11-5'], # Fall DST
|
||||
['2014-03-08', '2014-03-11'], # Spring DST
|
||||
['2014-01-01', '2014-01-03']] # Regular Time
|
||||
freqs = ['3H', '10T', '3601S', '3600001L', '3600000001U',
|
||||
'3600000000001N']
|
||||
|
||||
for tz in [None, 'Australia/Sydney', 'Asia/Tokyo', 'Europe/Paris',
|
||||
'US/Pacific', 'US/Eastern']:
|
||||
for date_pair in date_pairs:
|
||||
for freq in freqs:
|
||||
idx = date_range(date_pair[0], date_pair[
|
||||
1], freq=freq, tz=tz)
|
||||
assert idx.inferred_freq == freq
|
||||
|
||||
index = date_range("2013-11-03", periods=5,
|
||||
freq="3H").tz_localize("America/Chicago")
|
||||
assert index.inferred_freq is None
|
||||
|
||||
def test_infer_freq_businesshour(self):
|
||||
# GH 7905
|
||||
idx = DatetimeIndex(
|
||||
['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'])
|
||||
# hourly freq in a day must result in 'H'
|
||||
assert idx.inferred_freq == 'H'
|
||||
|
||||
idx = DatetimeIndex(
|
||||
['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'])
|
||||
assert idx.inferred_freq == 'BH'
|
||||
|
||||
idx = DatetimeIndex(
|
||||
['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'])
|
||||
assert idx.inferred_freq == 'BH'
|
||||
|
||||
idx = DatetimeIndex(
|
||||
['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'])
|
||||
assert idx.inferred_freq == 'BH'
|
||||
|
||||
def test_not_monotonic(self):
|
||||
rng = _dti(['1/31/2000', '1/31/2001', '1/31/2002'])
|
||||
rng = rng[::-1]
|
||||
assert rng.inferred_freq == '-1A-JAN'
|
||||
|
||||
def test_non_datetimeindex2(self):
|
||||
rng = _dti(['1/31/2000', '1/31/2001', '1/31/2002'])
|
||||
|
||||
vals = rng.to_pydatetime()
|
||||
|
||||
result = frequencies.infer_freq(vals)
|
||||
assert result == rng.inferred_freq
|
||||
|
||||
def test_invalid_index_types(self):
|
||||
|
||||
# test all index types
|
||||
for i in [tm.makeIntIndex(10), tm.makeFloatIndex(10),
|
||||
tm.makePeriodIndex(10)]:
|
||||
pytest.raises(TypeError, lambda: frequencies.infer_freq(i))
|
||||
|
||||
# GH 10822
|
||||
# odd error message on conversions to datetime for unicode
|
||||
if not is_platform_windows():
|
||||
for i in [tm.makeStringIndex(10), tm.makeUnicodeIndex(10)]:
|
||||
pytest.raises(ValueError, lambda: frequencies.infer_freq(i))
|
||||
|
||||
def test_string_datetimelike_compat(self):
|
||||
|
||||
# GH 6463
|
||||
expected = frequencies.infer_freq(['2004-01', '2004-02', '2004-03',
|
||||
'2004-04'])
|
||||
result = frequencies.infer_freq(Index(['2004-01', '2004-02', '2004-03',
|
||||
'2004-04']))
|
||||
assert result == expected
|
||||
|
||||
def test_series(self):
|
||||
|
||||
# GH6407
|
||||
# inferring series
|
||||
|
||||
# invalid type of Series
|
||||
for s in [Series(np.arange(10)), Series(np.arange(10.))]:
|
||||
pytest.raises(TypeError, lambda: frequencies.infer_freq(s))
|
||||
|
||||
# a non-convertible string
|
||||
pytest.raises(ValueError, lambda: frequencies.infer_freq(
|
||||
Series(['foo', 'bar'])))
|
||||
|
||||
# cannot infer on PeriodIndex
|
||||
for freq in [None, 'L']:
|
||||
s = Series(period_range('2013', periods=10, freq=freq))
|
||||
pytest.raises(TypeError, lambda: frequencies.infer_freq(s))
|
||||
|
||||
# DateTimeIndex
|
||||
for freq in ['M', 'L', 'S']:
|
||||
s = Series(date_range('20130101', periods=10, freq=freq))
|
||||
inferred = frequencies.infer_freq(s)
|
||||
assert inferred == freq
|
||||
|
||||
s = Series(date_range('20130101', '20130110'))
|
||||
inferred = frequencies.infer_freq(s)
|
||||
assert inferred == 'D'
|
||||
|
||||
def test_legacy_offset_warnings(self):
|
||||
freqs = ['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']
|
||||
|
||||
msg = INVALID_FREQ_ERR_MSG
|
||||
for freq in freqs:
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
frequencies.get_offset(freq)
|
||||
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
date_range('2011-01-01', periods=5, freq=freq)
|
||||
@@ -0,0 +1,382 @@
|
||||
from datetime import datetime
|
||||
|
||||
import pytest
|
||||
from pytz import utc
|
||||
|
||||
from pandas import DatetimeIndex, compat
|
||||
import pandas.util.testing as tm
|
||||
|
||||
from pandas.tseries.holiday import (
|
||||
MO, SA, AbstractHolidayCalendar, DateOffset, EasterMonday, GoodFriday,
|
||||
Holiday, HolidayCalendarFactory, Timestamp, USColumbusDay,
|
||||
USFederalHolidayCalendar, USLaborDay, USMartinLutherKingJr, USMemorialDay,
|
||||
USPresidentsDay, USThanksgivingDay, after_nearest_workday,
|
||||
before_nearest_workday, get_calendar, nearest_workday, next_monday,
|
||||
next_monday_or_tuesday, next_workday, previous_friday, previous_workday,
|
||||
sunday_to_monday, weekend_to_monday)
|
||||
|
||||
|
||||
class TestCalendar(object):
|
||||
|
||||
def setup_method(self, method):
|
||||
self.holiday_list = [
|
||||
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)]
|
||||
|
||||
self.start_date = datetime(2012, 1, 1)
|
||||
self.end_date = datetime(2012, 12, 31)
|
||||
|
||||
def test_calendar(self):
|
||||
|
||||
calendar = USFederalHolidayCalendar()
|
||||
holidays = calendar.holidays(self.start_date, self.end_date)
|
||||
|
||||
holidays_1 = calendar.holidays(
|
||||
self.start_date.strftime('%Y-%m-%d'),
|
||||
self.end_date.strftime('%Y-%m-%d'))
|
||||
holidays_2 = calendar.holidays(
|
||||
Timestamp(self.start_date),
|
||||
Timestamp(self.end_date))
|
||||
|
||||
assert list(holidays.to_pydatetime()) == self.holiday_list
|
||||
assert list(holidays_1.to_pydatetime()) == self.holiday_list
|
||||
assert list(holidays_2.to_pydatetime()) == self.holiday_list
|
||||
|
||||
def test_calendar_caching(self):
|
||||
# Test for issue #9552
|
||||
|
||||
class TestCalendar(AbstractHolidayCalendar):
|
||||
|
||||
def __init__(self, name=None, rules=None):
|
||||
super(TestCalendar, self).__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)])
|
||||
|
||||
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(self):
|
||||
# Test for issue 11477
|
||||
USFedCal = get_calendar('USFederalHolidayCalendar')
|
||||
holidays0 = USFedCal.holidays(datetime(2015, 7, 3), datetime(
|
||||
2015, 7, 3)) # <-- same start and end dates
|
||||
holidays1 = USFedCal.holidays(datetime(2015, 7, 3), datetime(
|
||||
2015, 7, 6)) # <-- different start and end dates
|
||||
holidays2 = USFedCal.holidays(datetime(2015, 7, 3), datetime(
|
||||
2015, 7, 3)) # <-- same start and end dates
|
||||
|
||||
tm.assert_index_equal(holidays0, holidays1)
|
||||
tm.assert_index_equal(holidays0, holidays2)
|
||||
|
||||
def test_rule_from_name(self):
|
||||
USFedCal = get_calendar('USFederalHolidayCalendar')
|
||||
assert USFedCal.rule_from_name('Thanksgiving') == USThanksgivingDay
|
||||
|
||||
|
||||
class TestHoliday(object):
|
||||
|
||||
def setup_method(self, method):
|
||||
self.start_date = datetime(2011, 1, 1)
|
||||
self.end_date = datetime(2020, 12, 31)
|
||||
|
||||
def check_results(self, holiday, start, end, expected):
|
||||
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])
|
||||
|
||||
def test_usmemorialday(self):
|
||||
self.check_results(holiday=USMemorialDay,
|
||||
start=self.start_date,
|
||||
end=self.end_date,
|
||||
expected=[
|
||||
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),
|
||||
], )
|
||||
|
||||
def test_non_observed_holiday(self):
|
||||
|
||||
self.check_results(
|
||||
Holiday('July 4th Eve', month=7, day=3),
|
||||
start="2001-01-01",
|
||||
end="2003-03-03",
|
||||
expected=[
|
||||
Timestamp('2001-07-03 00:00:00'),
|
||||
Timestamp('2002-07-03 00:00:00')
|
||||
]
|
||||
)
|
||||
|
||||
self.check_results(
|
||||
Holiday('July 4th Eve', month=7, day=3, days_of_week=(0, 1, 2, 3)),
|
||||
start="2001-01-01",
|
||||
end="2008-03-03",
|
||||
expected=[
|
||||
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'),
|
||||
]
|
||||
)
|
||||
|
||||
def test_easter(self):
|
||||
|
||||
self.check_results(EasterMonday,
|
||||
start=self.start_date,
|
||||
end=self.end_date,
|
||||
expected=[
|
||||
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'),
|
||||
], )
|
||||
self.check_results(GoodFriday,
|
||||
start=self.start_date,
|
||||
end=self.end_date,
|
||||
expected=[
|
||||
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'),
|
||||
], )
|
||||
|
||||
def test_usthanksgivingday(self):
|
||||
|
||||
self.check_results(USThanksgivingDay,
|
||||
start=self.start_date,
|
||||
end=self.end_date,
|
||||
expected=[
|
||||
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_holidays_within_dates(self):
|
||||
# Fix holiday behavior found in #11477
|
||||
# where holiday.dates returned dates outside start/end date
|
||||
# or observed rules could not be applied as the holiday
|
||||
# was not in the original date range (e.g., 7/4/2015 -> 7/3/2015)
|
||||
start_date = datetime(2015, 7, 1)
|
||||
end_date = datetime(2015, 7, 1)
|
||||
|
||||
calendar = get_calendar('USFederalHolidayCalendar')
|
||||
new_years = calendar.rule_from_name('New Years Day')
|
||||
july_4th = calendar.rule_from_name('July 4th')
|
||||
veterans_day = calendar.rule_from_name('Veterans Day')
|
||||
christmas = calendar.rule_from_name('Christmas')
|
||||
|
||||
# Holiday: (start/end date, holiday)
|
||||
holidays = {USMemorialDay: ("2015-05-25", "2015-05-25"),
|
||||
USLaborDay: ("2015-09-07", "2015-09-07"),
|
||||
USColumbusDay: ("2015-10-12", "2015-10-12"),
|
||||
USThanksgivingDay: ("2015-11-26", "2015-11-26"),
|
||||
USMartinLutherKingJr: ("2015-01-19", "2015-01-19"),
|
||||
USPresidentsDay: ("2015-02-16", "2015-02-16"),
|
||||
GoodFriday: ("2015-04-03", "2015-04-03"),
|
||||
EasterMonday: [("2015-04-06", "2015-04-06"),
|
||||
("2015-04-05", [])],
|
||||
new_years: [("2015-01-01", "2015-01-01"),
|
||||
("2011-01-01", []),
|
||||
("2010-12-31", "2010-12-31")],
|
||||
july_4th: [("2015-07-03", "2015-07-03"),
|
||||
("2015-07-04", [])],
|
||||
veterans_day: [("2012-11-11", []),
|
||||
("2012-11-12", "2012-11-12")],
|
||||
christmas: [("2011-12-25", []),
|
||||
("2011-12-26", "2011-12-26")]}
|
||||
|
||||
for rule, dates in compat.iteritems(holidays):
|
||||
empty_dates = rule.dates(start_date, end_date)
|
||||
assert empty_dates.tolist() == []
|
||||
|
||||
if isinstance(dates, tuple):
|
||||
dates = [dates]
|
||||
|
||||
for start, expected in dates:
|
||||
if len(expected):
|
||||
expected = [Timestamp(expected)]
|
||||
self.check_results(rule, start, start, expected)
|
||||
|
||||
def test_argument_types(self):
|
||||
holidays = USThanksgivingDay.dates(self.start_date, self.end_date)
|
||||
|
||||
holidays_1 = USThanksgivingDay.dates(
|
||||
self.start_date.strftime('%Y-%m-%d'),
|
||||
self.end_date.strftime('%Y-%m-%d'))
|
||||
|
||||
holidays_2 = USThanksgivingDay.dates(
|
||||
Timestamp(self.start_date),
|
||||
Timestamp(self.end_date))
|
||||
|
||||
tm.assert_index_equal(holidays, holidays_1)
|
||||
tm.assert_index_equal(holidays, holidays_2)
|
||||
|
||||
def test_special_holidays(self):
|
||||
base_date = [datetime(2012, 5, 28)]
|
||||
holiday_1 = Holiday('One-Time', year=2012, month=5, day=28)
|
||||
holiday_2 = Holiday('Range', month=5, day=28,
|
||||
start_date=datetime(2012, 1, 1),
|
||||
end_date=datetime(2012, 12, 31),
|
||||
offset=DateOffset(weekday=MO(1)))
|
||||
|
||||
assert base_date == holiday_1.dates(self.start_date, self.end_date)
|
||||
assert base_date == holiday_2.dates(self.start_date, self.end_date)
|
||||
|
||||
def test_get_calendar(self):
|
||||
class TestCalendar(AbstractHolidayCalendar):
|
||||
rules = []
|
||||
|
||||
calendar = get_calendar('TestCalendar')
|
||||
assert TestCalendar == calendar.__class__
|
||||
|
||||
def test_factory(self):
|
||||
class_1 = HolidayCalendarFactory('MemorialDay',
|
||||
AbstractHolidayCalendar,
|
||||
USMemorialDay)
|
||||
class_2 = HolidayCalendarFactory('Thansksgiving',
|
||||
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
|
||||
|
||||
|
||||
class TestObservanceRules(object):
|
||||
|
||||
def setup_method(self, method):
|
||||
self.we = datetime(2014, 4, 9)
|
||||
self.th = datetime(2014, 4, 10)
|
||||
self.fr = datetime(2014, 4, 11)
|
||||
self.sa = datetime(2014, 4, 12)
|
||||
self.su = datetime(2014, 4, 13)
|
||||
self.mo = datetime(2014, 4, 14)
|
||||
self.tu = datetime(2014, 4, 15)
|
||||
|
||||
def test_next_monday(self):
|
||||
assert next_monday(self.sa) == self.mo
|
||||
assert next_monday(self.su) == self.mo
|
||||
|
||||
def test_next_monday_or_tuesday(self):
|
||||
assert next_monday_or_tuesday(self.sa) == self.mo
|
||||
assert next_monday_or_tuesday(self.su) == self.tu
|
||||
assert next_monday_or_tuesday(self.mo) == self.tu
|
||||
|
||||
def test_previous_friday(self):
|
||||
assert previous_friday(self.sa) == self.fr
|
||||
assert previous_friday(self.su) == self.fr
|
||||
|
||||
def test_sunday_to_monday(self):
|
||||
assert sunday_to_monday(self.su) == self.mo
|
||||
|
||||
def test_nearest_workday(self):
|
||||
assert nearest_workday(self.sa) == self.fr
|
||||
assert nearest_workday(self.su) == self.mo
|
||||
assert nearest_workday(self.mo) == self.mo
|
||||
|
||||
def test_weekend_to_monday(self):
|
||||
assert weekend_to_monday(self.sa) == self.mo
|
||||
assert weekend_to_monday(self.su) == self.mo
|
||||
assert weekend_to_monday(self.mo) == self.mo
|
||||
|
||||
def test_next_workday(self):
|
||||
assert next_workday(self.sa) == self.mo
|
||||
assert next_workday(self.su) == self.mo
|
||||
assert next_workday(self.mo) == self.tu
|
||||
|
||||
def test_previous_workday(self):
|
||||
assert previous_workday(self.sa) == self.fr
|
||||
assert previous_workday(self.su) == self.fr
|
||||
assert previous_workday(self.tu) == self.mo
|
||||
|
||||
def test_before_nearest_workday(self):
|
||||
assert before_nearest_workday(self.sa) == self.th
|
||||
assert before_nearest_workday(self.su) == self.fr
|
||||
assert before_nearest_workday(self.tu) == self.mo
|
||||
|
||||
def test_after_nearest_workday(self):
|
||||
assert after_nearest_workday(self.sa) == self.mo
|
||||
assert after_nearest_workday(self.su) == self.tu
|
||||
assert after_nearest_workday(self.fr) == self.mo
|
||||
|
||||
|
||||
class TestFederalHolidayCalendar(object):
|
||||
|
||||
def test_no_mlk_before_1986(self):
|
||||
# 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(self):
|
||||
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)]
|
||||
|
||||
|
||||
class TestHolidayConflictingArguments(object):
|
||||
|
||||
def test_both_offset_observance_raises(self):
|
||||
# see gh-10217
|
||||
with pytest.raises(NotImplementedError):
|
||||
Holiday("Cyber Monday", month=11, day=1,
|
||||
offset=[DateOffset(weekday=SA(4))],
|
||||
observance=next_monday)
|
||||
Reference in New Issue
Block a user