# Path: huTools/calendar/tools.py
# def date_trunc(trtype, timestamp):
#     """
#     Truncate date or datetime object. Truncated object of the given type.
# 
#     This function is inspired by date_trunc from PostgreSQL, see
#     http://www.postgresql.org/docs/8.1/static/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC
# 
#     Supported types are year, quarter, month, week, day, hour, minute, second.
# 
#     >>> date_trunc('week', datetime.datetime(1974, 8, 21))
#     datetime.datetime(1974, 8, 19, 0, 0)
#     >>> date_trunc('week', datetime.date(1973, 8, 8))
#     datetime.date(1973, 8, 6)
#     """
# 
#     if isinstance(timestamp, basestring):
#         # we are called with the old calling convention
#         warnings.warn("`date_trunc` should be called with a date/datetime object as the second parameter",
#                       DeprecationWarning, stacklevel=2)
#         timestamp, trtype = trtype, timestamp
# 
#     tmp = timestamp.timetuple()
#     if trtype == "year":
#         ret = datetime.datetime(tmp.tm_year, 1, 1)
#     elif trtype == "tertial":
#         ret = datetime.datetime(tmp.tm_year, 1 + (get_tertial(timestamp) - 1) * 4, 1)
#     elif trtype == "quarter":
#         ret = datetime.datetime(tmp.tm_year, 3 * (get_quarter(timestamp) - 1) + 1, 1)
#     elif trtype == "month":
#         ret = datetime.datetime(tmp.tm_year, tmp.tm_mon, 1)
#     elif trtype == "week":
#         firstday = timestamp - datetime.timedelta(days=tmp.tm_wday)
#         ret = datetime.datetime.combine(firstday, datetime.time(0))
#     elif trtype == "day":
#         ret = datetime.datetime(tmp.tm_year, tmp.tm_mon, tmp.tm_mday)
#     elif trtype == "hour":
#         ret = datetime.datetime(tmp.tm_year, tmp.tm_mon, tmp.tm_mday, tmp.tm_hour)
#     elif trtype == "minute":
#         ret = datetime.datetime(tmp.tm_year, tmp.tm_mon, tmp.tm_mday, tmp.tm_hour, tmp.tm_min)
#     elif trtype == "second":
#         ret = datetime.datetime(tmp.tm_year, tmp.tm_mon, tmp.tm_mday, tmp.tm_hour, tmp.tm_min, tmp.tm_sec)
#     else:
#         raise ValueError("Unknown truncation type %s" % trtype)
#     # if we where given a datetime object return it, else assume a date object and cast our return
#     # value to that
#     if isinstance(timestamp, datetime.datetime):
#         return ret
#     return ret.date()


from huTools.calendar.tools import date_trunc
    import doctest
    import datetime
def group_by_quarter(values, aggregationfunc):
    """input should be [(datetime, stuff), ...]

    >>> indata = [(datetime.date(2012, 1, 30), 1), (datetime.date(2012, 1, 31), 3),
    ...           (datetime.date(2012, 1, 1), -1), (datetime.date(2011, 12, 12), 0)]
    >>> group_by_quarter(indata, min)
    [(datetime.date(2011, 10, 1), 0), (datetime.date(2012, 1, 1), -1)]
    """
    return _group_by_x(values, aggregationfunc, lambda x: date_trunc('quarter', x))


def group_by_tertial(values, aggregationfunc):
    """input should be [(datetime, stuff), ...]

    >>> indata = [(datetime.date(2012, 1, 31), 1), (datetime.date(2012, 4, 30), 3),
    ...           (datetime.date(2012, 1, 1), -1), (datetime.date(2011, 12, 12), 0)]
    >>> group_by_tertial(indata, avg)
    [(datetime.date(2011, 9, 1), 0.0), (datetime.date(2012, 1, 1), 1.0)]
    """
    return _group_by_x(values, aggregationfunc, lambda x: date_trunc('tertial', x))


def group_by_year(values, aggregationfunc):
    """input should be [(datetime, stuff), ...]

    >>> indata = [(datetime.date(2012, 1, 31), 1), (datetime.date(2012, 4, 30), 3),
    ...           (datetime.date(2012, 1, 1), -1), (datetime.date(2011, 12, 12), 0)]
    >>> group_by_year(indata, max)
    [(datetime.date(2011, 1, 1), 0), (datetime.date(2012, 1, 1), 3)]
    """

# Path: huTools/calendar/tools.py
# def date_trunc(trtype, timestamp):
#     """
#     Truncate date or datetime object. Truncated object of the given type.
# 
#     This function is inspired by date_trunc from PostgreSQL, see
#     http://www.postgresql.org/docs/8.1/static/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC
# 
#     Supported types are year, quarter, month, week, day, hour, minute, second.
# 
#     >>> date_trunc('week', datetime.datetime(1974, 8, 21))
#     datetime.datetime(1974, 8, 19, 0, 0)
#     >>> date_trunc('week', datetime.date(1973, 8, 8))
#     datetime.date(1973, 8, 6)
#     """
# 
#     if isinstance(timestamp, basestring):
#         # we are called with the old calling convention
#         warnings.warn("`date_trunc` should be called with a date/datetime object as the second parameter",
#                       DeprecationWarning, stacklevel=2)
#         timestamp, trtype = trtype, timestamp
# 
#     tmp = timestamp.timetuple()
#     if trtype == "year":
#         ret = datetime.datetime(tmp.tm_year, 1, 1)
#     elif trtype == "tertial":
#         ret = datetime.datetime(tmp.tm_year, 1 + (get_tertial(timestamp) - 1) * 4, 1)
#     elif trtype == "quarter":
#         ret = datetime.datetime(tmp.tm_year, 3 * (get_quarter(timestamp) - 1) + 1, 1)
#     elif trtype == "month":
#         ret = datetime.datetime(tmp.tm_year, tmp.tm_mon, 1)
#     elif trtype == "week":
#         firstday = timestamp - datetime.timedelta(days=tmp.tm_wday)
#         ret = datetime.datetime.combine(firstday, datetime.time(0))
#     elif trtype == "day":
#         ret = datetime.datetime(tmp.tm_year, tmp.tm_mon, tmp.tm_mday)
#     elif trtype == "hour":
#         ret = datetime.datetime(tmp.tm_year, tmp.tm_mon, tmp.tm_mday, tmp.tm_hour)
#     elif trtype == "minute":
#         ret = datetime.datetime(tmp.tm_year, tmp.tm_mon, tmp.tm_mday, tmp.tm_hour, tmp.tm_min)
#     elif trtype == "second":
#         ret = datetime.datetime(tmp.tm_year, tmp.tm_mon, tmp.tm_mday, tmp.tm_hour, tmp.tm_min, tmp.tm_sec)
#     else:
#         raise ValueError("Unknown truncation type %s" % trtype)
#     # if we where given a datetime object return it, else assume a date object and cast our return
#     # value to that
#     if isinstance(timestamp, datetime.datetime):
#         return ret
#     return ret.date()


# Path: huTools/aggregation.py
from huTools.calendar.tools import date_trunc
    import doctest
    import datetime

def group_by_quarter(values, aggregationfunc):
    """input should be [(datetime, stuff), ...]

    >>> indata = [(datetime.date(2012, 1, 30), 1), (datetime.date(2012, 1, 31), 3),
    ...           (datetime.date(2012, 1, 1), -1), (datetime.date(2011, 12, 12), 0)]
    >>> group_by_quarter(indata, min)
    [(datetime.date(2011, 10, 1), 0), (datetime.date(2012, 1, 1), -1)]
    """
    return _group_by_x(values, aggregationfunc, lambda x: date_trunc('quarter', x))


def group_by_tertial(values, aggregationfunc):
    """input should be [(datetime, stuff), ...]

    >>> indata = [(datetime.date(2012, 1, 31), 1), (datetime.date(2012, 4, 30), 3),
    ...           (datetime.date(2012, 1, 1), -1), (datetime.date(2011, 12, 12), 0)]
    >>> group_by_tertial(indata, avg)
    [(datetime.date(2011, 9, 1), 0.0), (datetime.date(2012, 1, 1), 1.0)]
    """
    return _group_by_x(values, aggregationfunc, lambda x: date_trunc('tertial', x))


def group_by_year(values, aggregationfunc):
    """input should be [(datetime, stuff), ...]

    >>> indata = [(datetime.date(2012, 1, 31), 1), (datetime.date(2012, 4, 30), 3),
    ...           (datetime.date(2012, 1, 1), -1), (datetime.date(2011, 12, 12), 0)]
    >>> group_by_year(indata, max)
    [(datetime.date(2011, 1, 1), 0), (datetime.date(2012, 1, 1), 3)]
    """

    return _group_by_x(values, aggregationfunc, lambda x: date_trunc('year', x))