# Class Date supplies date objects that support date arithmetic.
#
# Date(month,day,year) returns a Date object.  An instance prints as,
# e.g., 'Mon 16 Aug 1993'.
#
# Addition, subtraction, comparison operators, min, max, and sorting
# all work as expected for date objects:  int+date or date+int returns
# the date `int' days from `date'; date+date raises an exception;
# date-int returns the date `int' days before `date'; date2-date1 returns
# an integer, the number of days from date1 to date2; int-date raises an
# exception; date1 < date2 is true iff date1 occurs before date2 (&
# similarly for other comparisons); min(date1,date2) is the earlier of
# the two dates and max(date1,date2) the later; and date objects can be
# used as dictionary keys.
#
# Date objects support one visible method, date.weekday().  This returns
# the day of the week the date falls on, as a string.
#
# Date objects also have 4 read-only data attributes:
#   .month  in 1..12
#   .day    in 1..31
#   .year   int or long int
#   .ord    the ordinal of the date relative to an arbitrary staring point
#
# The Dates module also supplies function today(), which returns the
# current date as a date object.
#
# Those entranced by calendar trivia will be disappointed, as no attempt
# has been made to accommodate the Julian (etc) system.  On the other
# hand, at least this package knows that 2000 is a leap year but 2100
# isn't, and works fine for years with a hundred decimal digits <wink>.

# Tim Peters   tim@ksr.com
# not speaking for Kendall Square Research Corp

# Adapted to Python 1.1 (where some hacks to overcome coercion are unnecessary)
# by Guido van Rossum

# Note that as of Python 2.3, a datetime module is included in the stardard
# library.

# vi:set tabsize=8:

_MONTH_NAMES = [ 'January', 'February', 'March', 'April', 'May',
                 'June', 'July', 'August', 'September', 'October',
                 'November', 'December' ]

_DAY_NAMES = [ 'Friday', 'Saturday', 'Sunday', 'Monday',
               'Tuesday', 'Wednesday', 'Thursday' ]

_DAYS_IN_MONTH = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]

_DAYS_BEFORE_MONTH = []
dbm = 0
for dim in _DAYS_IN_MONTH:
    _DAYS_BEFORE_MONTH.append(dbm)
    dbm = dbm + dim
del dbm, dim

_INT_TYPES = type(1), type(1)

def _is_leap(year):           # 1 if leap year, else 0
    if year % 4 != 0: return 0
    if year % 400 == 0: return 1
    return year % 100 != 0

def _days_in_year(year):      # number of days in year
    return 365 + _is_leap(year)

def _days_before_year(year):  # number of days before year
    return year*365 + (year+3)/4 - (year+99)/100 + (year+399)/400

def _days_in_month(month, year):      # number of days in month of year
    if month == 2 and _is_leap(year): return 29
    return _DAYS_IN_MONTH[month-1]

def _days_before_month(month, year):  # number of days in year before month
    return _DAYS_BEFORE_MONTH[month-1] + (month > 2 and _is_leap(year))

def _date2num(date):          # compute ordinal of date.month,day,year
    return _days_before_year(date.year) + \
           _days_before_month(date.month, date.year) + \
           date.day

_DI400Y = _days_before_year(400)      # number of days in 400 years

def _num2date(n):             # return date with ordinal n
    if type(n) not in _INT_TYPES:
        raise TypeError('argument must be integer: %r' % type(n))

    ans = Date(1,1,1)   # arguments irrelevant; just getting a Date obj
    del ans.ord, ans.month, ans.day, ans.year # un-initialize it
    ans.ord = n

    n400 = (n-1)/_DI400Y                # # of 400-year blocks preceding
    year, n = 400 * n400, n - _DI400Y * n400
    more = n / 365
    dby = _days_before_year(more)
    if dby >= n:
        more = more - 1
        dby = dby - _days_in_year(more)
    year, n = year + more, int(n - dby)

    try: year = int(year)               # chop to int, if it fits
    except (ValueError, OverflowError): pass

    month = min(n/29 + 1, 12)
    dbm = _days_before_month(month, year)
    if dbm >= n:
        month = month - 1
        dbm = dbm - _days_in_month(month, year)

    ans.month, ans.day, ans.year = month, n-dbm, year
    return ans

def _num2day(n):      # return weekday name of day with ordinal n
    return _DAY_NAMES[ int(n % 7) ]


class Date:
    def __init__(self, month, day, year):
        if not 1 <= month <= 12:
            raise ValueError('month must be in 1..12: %r' % (month,))
        dim = _days_in_month(month, year)
        if not 1 <= day <= dim:
            raise ValueError('day must be in 1..%r: %r' % (dim, day))
        self.month, self.day, self.year = month, day, year
        self.ord = _date2num(self)

    # don't allow setting existing attributes
    def __setattr__(self, name, value):
        if name in self.__dict__:
            raise AttributeError('read-only attribute ' + name)
        self.__dict__[name] = value

    def __cmp__(self, other):
        return cmp(self.ord, other.ord)

    # define a hash function so dates can be used as dictionary keys
    def __hash__(self):
        return hash(self.ord)

    # print as, e.g., Mon 16 Aug 1993
    def __repr__(self):
        return '%.3s %2d %.3s %r' % (
              self.weekday(),
              self.day,
              _MONTH_NAMES[self.month-1],
              self.year)

    # Python 1.1 coerces neither int+date nor date+int
    def __add__(self, n):
        if type(n) not in _INT_TYPES:
            raise TypeError('can\'t add %r to date' % type(n))
        return _num2date(self.ord + n)
    __radd__ = __add__ # handle int+date

    # Python 1.1 coerces neither date-int nor date-date
    def __sub__(self, other):
        if type(other) in _INT_TYPES:           # date-int
            return _num2date(self.ord - other)
        else:
            return self.ord - other.ord         # date-date

    # complain about int-date
    def __rsub__(self, other):
        raise TypeError('Can\'t subtract date from integer')

    def weekday(self):
        return _num2day(self.ord)

def today():
    import time
    local = time.localtime(time.time())
    return Date(local[1], local[2], local[0])

DateTestError = 'DateTestError'
def test(firstyear, lastyear):
    a = Date(9,30,1913)
    b = Date(9,30,1914)
    if repr(a) != 'Tue 30 Sep 1913':
        raise DateTestError('__repr__ failure')
    if (not a < b) or a == b or a > b or b != b:
        raise DateTestError('__cmp__ failure')
    if a+365 != b or 365+a != b:
        raise DateTestError('__add__ failure')
    if b-a != 365 or b-365 != a:
        raise DateTestError('__sub__ failure')
    try:
        x = 1 - a
        raise DateTestError('int-date should have failed')
    except TypeError:
        pass
    try:
        x = a + b
        raise DateTestError('date+date should have failed')
    except TypeError:
        pass
    if a.weekday() != 'Tuesday':
        raise DateTestError('weekday() failure')
    if max(a,b) is not b or min(a,b) is not a:
        raise DateTestError('min/max failure')
    d = {a-1:b, b:a+1}
    if d[b-366] != b or d[a+(b-a)] != Date(10,1,1913):
        raise DateTestError('dictionary failure')

    # verify date<->number conversions for first and last days for
    # all years in firstyear .. lastyear

    lord = _days_before_year(firstyear)
    y = firstyear
    while y <= lastyear:
        ford = lord + 1
        lord = ford + _days_in_year(y) - 1
        fd, ld = Date(1,1,y), Date(12,31,y)
        if (fd.ord,ld.ord) != (ford,lord):
            raise DateTestError('date->num failed', y)
        fd, ld = _num2date(ford), _num2date(lord)
        if (1,1,y,12,31,y) != \
           (fd.month,fd.day,fd.year,ld.month,ld.day,ld.year):
            raise DateTestError('num->date failed', y)
        y = y + 1
