Prints a discordian calendar for a particular season and year.

    Args::

        season: integer cardinal season from 1 to 5
        year: integer discordian year from 1166 to MAXYEAR + 1166
        dtobj: datetime object to instatiate the calendar from (Gregorian)

def discordian_calendar(season=None, year=None, dtobj=None):
    """Prints a discordian calendar for a particular season and year.

    Args::

        season: integer cardinal season from 1 to 5
        year: integer discordian year from 1166 to MAXYEAR + 1166
        dtobj: datetime object to instatiate the calendar from (Gregorian)
    """

    now = DDate(dtobj)

    moved_year = None

    if season is None:
        season = now.season
    elif season.lower() == "next":
        season, moved_year = _season_overflow(now.season or 0 + 1, moved_year,
                                              now)
    else:
        # allow for +1, -2, for seasons...
        for symbol, oper in zip(("+", "-"), (operator.add, operator.sub)):
            if symbol in season:
                try:
                    amount = int(season.strip(symbol))
                except ValueError:
                    raise ValueError("unknown season: {}".format(season))
                else:
                    season, moved_year = _season_overflow(
                        oper(now.season or 0, amount),
                        moved_year,
                        now,
                    )
                    break
        else:
            # allow to use the season name or some starting part of it
            input_name = season.lower()
            for season_name in now.SEASONS:
                _name = season_name.lower()
                if input_name == _name or any(
                        [n.startswith(input_name) for n in _name.split(" ")]):
                    season = now.SEASONS.index(season_name)
                    break
            else:
                try:  # last try with a literal int being passed in
                    season = int(season)
                except ValueError:
                    raise ValueError("unknown season: {}".format(season))
                else:
                    if not 1 <= season <= 5:
                        raise ValueError("season must be in 1..5")
                    season -= 1  # allowing cardinal numbers from the user

    if year is None:
        year = moved_year or now.year
    elif year.lower() == "next":
        year = (moved_year or now.year) + 1
    else:
        for symbol, oper in zip(("+", "-"), (operator.add, operator.sub)):
            if symbol in year:
                year = oper(moved_year or now.year, int(year.strip(symbol)))
                break
        else:
            try:
                year = int(year)
            except ValueError:
                raise ValueError("invalid year: {}".format(year))

    if not MINYEAR <= year <= MAXYEAR:
        # otherwise this error isn't that helpful
        raise ValueError("year must be in {}..{}".format(MINYEAR, MAXYEAR))

    if now.day_of_season is None:
        if is_leap_year(year - 1166):
            day_of_season = None
        else:
            day_of_season = 59
        season = season or 0
    else:
        day_of_season = now.day_of_season

    if day_of_season:
        cal_date = DDate(year=year, season=season, day_of_season=day_of_season)
        cal = MultiCalendar(discordian=True, date=cal_date)
        cal.print_calendar()
    else:
        print("{} in YOLD {}".format(now.holiday, year))