# 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

# 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(1L)

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*365L + (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: ' + `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: ' + `month`
        dim = _days_in_month( month, year )
        if not 1 <= day <= dim:
            raise ValueError, 'day must be in 1..' + `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 self.__dict__.has_key(name):
            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 ' % (
              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 ' + `type(n)` + ' to date'
        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 `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
