Code Sample, a copy-pastable example if possible

import datetime
from pandas.tseries.offsets import CustomBusinessDay
from pandas.tseries.holiday import AbstractHolidayCalendar, Holiday, \
    USMartinLutherKingJr, USPresidentsDay, USMemorialDay, USLaborDay, \
    USThanksgivingDay, GoodFriday, nearest_workday
import pandas as pd
from pandas.tseries.offsets import BDay

class TradingCalendar(AbstractHolidayCalendar):
    """Calendar of trading holidays in the US"""
    rules = [
        Holiday('New Years Day', month=1, day=1, observance=nearest_workday),
        USMartinLutherKingJr,
        USPresidentsDay,
        USMemorialDay,
        Holiday('July 4th', month=7, day=4, observance=nearest_workday),
        USLaborDay,
        USThanksgivingDay,
        GoodFriday,
        Holiday('Christmas', month=12, day=25, observance=nearest_workday)
    ]


class TradingDay(CustomBusinessDay):
    def __init__(self, n=1):
        super(TradingDay, self).__init__(n, calendar=TradingCalendar())

r = pd.date_range(datetime.datetime(2017, 12, 26), datetime.datetime(2017, 1, 6), TradingDay(1))
len(r) == 9

Problem description

If you use a standard BDay() in the date_range() call, everything works as expected. However, if you use a CustomBusinessDay, it ends with a TypeError:

Traceback (most recent call last):
  File "/Users/bspeice/Development/datemath.py", line 102, in trading_range
    return pd.date_range(start, end, freq=TradingDay(skip))
  File "/Users/bspeice/venvs/scientific/lib/python2.7/site-packages/pandas/tseries/index.py", line 2023, in date_range
    closed=closed, **kwargs)
  File "/Users/bspeice/venvs/scientific/lib/python2.7/site-packages/pandas/util/decorators.py", line 91, in wrapper
    return func(*args, **kwargs)
  File "/Users/bspeice/venvs/scientific/lib/python2.7/site-packages/pandas/tseries/index.py", line 301, in __new__
    ambiguous=ambiguous)
  File "/Users/bspeice/venvs/scientific/lib/python2.7/site-packages/pandas/tseries/index.py", line 506, in _generate
    index = _generate_regular_range(start, end, periods, offset)
  File "/Users/bspeice/venvs/scientific/lib/python2.7/site-packages/pandas/tseries/index.py", line 1976, in _generate_regular_range
    dates = list(xdr)
  File "/Users/bspeice/venvs/scientific/lib/python2.7/site-packages/pandas/tseries/offsets.py", line 2881, in generate_range
    start = offset.rollforward(start)
  File "/Users/bspeice/venvs/scientific/lib/python2.7/site-packages/pandas/tseries/offsets.py", line 432, in rollforward
    dt = dt + self.__class__(1, normalize=self.normalize, **self.kwds)
TypeError: __init__() got an unexpected keyword argument 'normalize'

This error happens with every release from 0.18.0 - 0.19.2, I haven't tested outside this range.

Expected Output

True

Output of pd.show_versions()

INSTALLED VERSIONS ------------------ commit: None python: 2.7.13.final.0 python-bits: 64 OS: Darwin OS-release: 16.4.0 machine: x86_64 processor: i386 byteorder: little LC_ALL: None LANG: None LOCALE: None.None pandas: 0.19.2 nose: 1.3.7 pip: 9.0.1 setuptools: 34.3.0 Cython: None numpy: 1.12.0 scipy: 0.18.1 statsmodels: None xarray: None IPython: 5.2.2 sphinx: 1.5.2 patsy: 0.4.1 dateutil: 2.6.0 pytz: 2016.10 blosc: None bottleneck: None tables: None numexpr: None matplotlib: 2.0.0 openpyxl: None xlrd: 1.0.0 xlwt: None xlsxwriter: None lxml: None bs4: 4.5.3 html5lib: 0.9999999 httplib2: 0.10.3 apiclient: None sqlalchemy: None pymysql: None psycopg2: None jinja2: 2.9.5 boto: None pandas_datareader: None

Comment From: jreback

you are not using this according the docs: http://pandas.pydata.org/pandas-docs/stable/timeseries.html#custom-business-days-experimental

you need to pass the holidays to the CustomBusinessDay. In fact you are creating a new frequency (well you are trying to, but that is quite complicated).

Comment From: bspeice

It seems strange that I must first "realize" what the actual holiday dates are, before creating the CustomBusinessDay() object. I've attached the workaround code if anyone needs this in the future:

import datetime
from pandas.tseries.offsets import CustomBusinessDay
from pandas.tseries.holiday import AbstractHolidayCalendar, Holiday, \
    USMartinLutherKingJr, USPresidentsDay, USMemorialDay, USLaborDay, \
    USThanksgivingDay, GoodFriday, nearest_workday
import pandas as pd
from pandas.tseries.offsets import BDay

class TradingCalendar(AbstractHolidayCalendar):
    """Calendar of trading holidays in the US"""
    rules = [
        Holiday('New Years Day', month=1, day=1, observance=nearest_workday),
        USMartinLutherKingJr,
        USPresidentsDay,
        USMemorialDay,
        Holiday('July 4th', month=7, day=4, observance=nearest_workday),
        USLaborDay,
        USThanksgivingDay,
        GoodFriday,
        Holiday('Christmas', month=12, day=25, observance=nearest_workday)
    ]

start = datetime.datetime(2017, 12, 26)
end = datetime.datetime(2017, 1, 6)

realized_days = TradingCalendar().calendar(start, end)
r = pd.date_range(start, end, freq=CustomBusinessDay(holidays=realized_days))
len(r) == 9

Comment From: jreback

@bspeice generally a holiday calendar is defined for a range of available dates (years possibly), this essentially the definition of a calendar itself.

constructing a range generates the ranges from that calendar. I think this is clear from the docs (as this is exactly what the example does), but if not you are welcome to submit a doc update. If you feel this is a bug, please be specific.

Comment From: bspeice

So, what I missed as a dumb mistake is that datetime.datetime(2017, 12, 26) is after datetime.datetime(2017, 1, 6). If you change it to datetime.datetime(2016, 12, 26) as was originally intended, my first method works correctly.

This is what I believe is a bug:

# TradingCalendar has been set up as in previous comments

# This works:
pd.date_range(datetime.datetime(2017, 12, 26), datetime.datetime(2017, 1, 9), freq=BDay())

# This also works:
pd.date_range(datetime.datetime(2017, 12, 26), datetime.datetime(2017, 1, 9), freq=CustomBusinessDay(calendar=TradingCalendar()))

# This does not work:
class TradingDay(CustomBusinessDay):
    def __init__(self):
        super(TradingDay, self).__init__(calendar=TradingCalendar())

pd.date_range(datetime.datetime(2017, 12, 26), datetime.datetime(2017, 1, 9), freq=TradingDay())
# ...
# TypeError: __init__() got an unexpected keyword argument 'normalize'

Comment From: jreback

@bspeice that's not a bug, you are not calling the constructor properly. As I said inheriting from a frequency requires you to follow the pattern (there are args, kwargs passed).

Comment From: bspeice

OK, then I'll just use the original CustomBusinessDay. Thanks for your assistance.