1616# Date objects support one visible method, date.weekday(). This returns
1717# the day of the week the date falls on, as a string.
1818#
19- # Date objects also have 4 (conceptually) read-only data attributes:
19+ # Date objects also have 4 read-only data attributes:
2020# .month in 1..12
2121# .day in 1..31
2222# .year int or long int
33333434# not speaking for Kendall Square Research Corp
3535
36+ # Adapted to Python 1.1 (where some hacks to overcome coercion are unnecessary)
37+ # by Guido van Rossum
38+
39+ # vi:set tabsize=8:
40+
3641_MONTH_NAMES = [ 'January' , 'February' , 'March' , 'April' , 'May' ,
3742 'June' , 'July' , 'August' , 'September' , 'October' ,
3843 'November' , 'December' ]
@@ -81,6 +86,7 @@ def _num2date( n ): # return date with ordinal n
8186 raise TypeError , 'argument must be integer: ' + `type(n)`
8287
8388 ans = Date (1 ,1 ,1 ) # arguments irrelevant; just getting a Date obj
89+ del ans .ord , ans .month , ans .day , ans .year # un-initialize it
8490 ans .ord = n
8591
8692 n400 = (n - 1 )/ _DI400Y # # of 400-year blocks preceding
@@ -93,7 +99,7 @@ def _num2date( n ): # return date with ordinal n
9399 year , n = year + more , int (n - dby )
94100
95101 try : year = int (year ) # chop to int, if it fits
96- except ValueError : pass
102+ except ( ValueError , OverflowError ) : pass
97103
98104 month = min ( n / 29 + 1 , 12 )
99105 dbm = _days_before_month ( month , year )
@@ -118,6 +124,12 @@ def __init__( self, month, day, year ):
118124 self .month , self .day , self .year = month , day , year
119125 self .ord = _date2num ( self )
120126
127+ # don't allow setting existing attributes
128+ def __setattr__ ( self , name , value ):
129+ if self .__dict__ .has_key (name ):
130+ raise AttributeError , 'read-only attribute ' + name
131+ self .__dict__ [name ] = value
132+
121133 def __cmp__ ( self , other ):
122134 return cmp ( self .ord , other .ord )
123135
@@ -132,52 +144,27 @@ def __repr__( self ):
132144 self .day ,
133145 _MONTH_NAMES [self .month - 1 ] ) + `self.year`
134146
135- # automatic coercion is a pain for date arithmetic, since e.g.
136- # date-date and date-int mean different things. So, in order to
137- # sneak integers past Python's coercion rules without losing the info
138- # that they're really integers (& not dates!), integers are disguised
139- # as instances of the derived class _DisguisedInt. That this works
140- # relies on undocumented behavior of Python's coercion rules.
141- def __coerce__ ( self , other ):
142- if type (other ) in _INT_TYPES :
143- return self , _DisguisedInt (other )
144- # if another Date, fine
145- if type (other ) is type (self ) and other .__class__ is Date :
146- return self , other
147-
148- # Python coerces int+date, but not date+int; in the former case,
149- # _DisguisedInt.__add__ handles it, so we only need to do
150- # date+int here
147+ # Python 1.1 coerces neither int+date nor date+int
151148 def __add__ ( self , n ):
152149 if type (n ) not in _INT_TYPES :
153150 raise TypeError , 'can\' t add ' + `type(n)` + ' to date'
154151 return _num2date ( self .ord + n )
152+ __radd__ = __add__ # handle int+date
155153
156- # Python coerces all of int-date, date-int and date-date; the first
157- # case winds up in _DisguisedInt.__sub__, leaving the latter two
158- # for us
154+ # Python 1.1 coerces neither date-int nor date-date
159155 def __sub__ ( self , other ):
160- if other . __class__ is _DisguisedInt : # date-int
161- return _num2date ( self .ord - other . ord )
156+ if type ( other ) in _INT_TYPES : # date-int
157+ return _num2date ( self .ord - other )
162158 else :
163159 return self .ord - other .ord # date-date
164160
165- def weekday ( self ):
166- return _num2day ( self .ord )
167-
168- # see comments before Date.__add__
169- class _DisguisedInt ( Date ):
170- def __init__ ( self , n ):
171- self .ord = n
172-
173- # handle int+date
174- def __add__ ( self , other ):
175- return other .__add__ ( self .ord )
176-
177161 # complain about int-date
178- def __sub__ ( self , other ):
162+ def __rsub__ ( self , other ):
179163 raise TypeError , 'Can\' t subtract date from integer'
180164
165+ def weekday ( self ):
166+ return _num2day ( self .ord )
167+
181168def today ():
182169 import time
183170 local = time .localtime (time .time ())
@@ -189,9 +176,7 @@ def test( firstyear, lastyear ):
189176 b = Date (9 ,30 ,1914 )
190177 if `a` != 'Tue 30 Sep 1913' :
191178 raise DateTestError , '__repr__ failure'
192- if (not a < b ) or a == b or a > b or b != b or \
193- a != 698982 or 698982 != a or \
194- (not a > 5 ) or (not 5 < a ):
179+ if (not a < b ) or a == b or a > b or b != b :
195180 raise DateTestError , '__cmp__ failure'
196181 if a + 365 != b or 365 + a != b :
197182 raise DateTestError , '__add__ failure'
0 commit comments