1 """ |
|
2 Python implementation courtesy of Drew Csillag (StarMedia Network, Inc.) |
|
3 |
|
4 This version has been somewhat modified by MAL. It is still fairly |
|
5 rough though and not necessarily high performance... |
|
6 |
|
7 XXX Still needs testing and checkup !!! |
|
8 |
|
9 WARNING: Using this file is only recommended if you really must |
|
10 use it for some reason. It is not being actively maintained ! |
|
11 |
|
12 """ |
|
13 |
|
14 __version__ = '1.2.0 [Python]' |
|
15 |
|
16 import time,types,exceptions,math |
|
17 |
|
18 ### Errors |
|
19 |
|
20 class Error(exceptions.StandardError): |
|
21 pass |
|
22 |
|
23 class RangeError(Error): |
|
24 pass |
|
25 |
|
26 ### Constants (internal use only) |
|
27 |
|
28 month_offset=( |
|
29 (0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365), |
|
30 (0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366), |
|
31 ) |
|
32 |
|
33 days_in_month=( |
|
34 (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31), |
|
35 (31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31), |
|
36 ) |
|
37 |
|
38 ### Helpers |
|
39 |
|
40 def _IS_LEAPYEAR(d): |
|
41 return ((d.year % 4 == 0) |
|
42 and ( |
|
43 (d.year % 100 != 0) |
|
44 or (d.year % 400 == 0) |
|
45 ) |
|
46 ) |
|
47 |
|
48 def _YEAROFFSET(d): |
|
49 return ( |
|
50 (d.year - 1) * 365 |
|
51 + (d.year - 1) / 4 |
|
52 - (d.year - 1) / 100 |
|
53 + (d.year - 1) / 400 |
|
54 ) |
|
55 |
|
56 class _EmptyClass: |
|
57 pass |
|
58 |
|
59 def createEmptyObject(Class, |
|
60 _EmptyClass=_EmptyClass): |
|
61 |
|
62 o = _EmptyClass() |
|
63 o.__class__ = Class |
|
64 return o |
|
65 |
|
66 ### DateTime class |
|
67 |
|
68 class DateTime: |
|
69 |
|
70 def __init__(self, year, month=1, day=1, hour=0, minute=0, second=0.0): |
|
71 |
|
72 second=1.0 * second |
|
73 if month <= 0: |
|
74 raise RangeError, "year out of range (>0)" |
|
75 |
|
76 #calculate absolute date |
|
77 leap = (year % 4 == 0) and ((year % 100 != 0) or (year % 400 == 0)) |
|
78 |
|
79 #Negative values indicate days relative to the years end |
|
80 if month < 0: |
|
81 month = month + 13 |
|
82 |
|
83 if not (month >= 1 and month <= 12): |
|
84 raise RangeError, "month out of range (1-12)" |
|
85 |
|
86 #Negative values indicate days relative to the months end |
|
87 if (day < 0): |
|
88 day = day + days_in_month[leap][month - 1] + 1; |
|
89 |
|
90 if not (day >= 1 and day <= days_in_month[leap][month - 1]): |
|
91 raise RangeError, "day out of range" |
|
92 |
|
93 year = year - 1 |
|
94 yearoffset = year * 365 + year / 4 - year / 100 + year / 400 |
|
95 year = year + 1 |
|
96 absdate = day + month_offset[leap][month - 1] + yearoffset; |
|
97 |
|
98 self.absdate = absdate |
|
99 self.year = year |
|
100 self.month = month |
|
101 self.day = day |
|
102 self.day_of_week = (absdate - 1) % 7 |
|
103 self.day_of_year = absdate - yearoffset |
|
104 self.days_in_month = days_in_month[leap][month - 1] |
|
105 comdate = absdate - 693594 |
|
106 |
|
107 if not (hour >=0 and hour <= 23): |
|
108 raise RangeError, "hour out of range (0-23)" |
|
109 if not (minute >= 0 and minute <= 59): |
|
110 raise RangeError, "minute out of range (0-59)" |
|
111 if not (second >= 0.0 and |
|
112 (second < 60.0 or |
|
113 (hour == 23 and minute == 59 and second < 61.0))): |
|
114 raise RangeError, "second out of range (0.0 - <60.0; <61.0 for 23:59)" |
|
115 |
|
116 self.abstime = (hour * 3600 + minute * 60) + second |
|
117 self.hour = hour |
|
118 self.minute = minute |
|
119 self.second = second |
|
120 self.dst = -1 |
|
121 self.tz = "???" |
|
122 self.is_leapyear = leap |
|
123 self.yearoffset = yearoffset |
|
124 self.iso_week = (self.year, self.day, self.day_of_week) |
|
125 |
|
126 if comdate < 0.0: |
|
127 comdate = comdate - self.abstime / 86400.0 |
|
128 else: |
|
129 comdate = comdate + self.abstime / 86400.0 |
|
130 |
|
131 self.comdate = comdate |
|
132 |
|
133 def COMDate(self): |
|
134 return self.comdate |
|
135 |
|
136 def __str__(self): |
|
137 return "%04d-%02d-%02d %02d:%02d:%05.2f" % ( |
|
138 self.year, self.month, self.day, self.hour, self.minute, |
|
139 self.second) |
|
140 |
|
141 def __getattr__(self, attr): |
|
142 if attr == 'mjd': |
|
143 return (self - mjd0).days |
|
144 elif attr == 'jdn': |
|
145 return (self - jdn0).days |
|
146 elif attr == 'tjd': |
|
147 return (self - jdn0).days % 10000 |
|
148 elif attr == 'tjd_myriad': |
|
149 return int((self - jdn0).days) / 10000 + 240 |
|
150 elif attr == 'absdays': |
|
151 return self.absdate - 1 + self.abstime / 86400.0 |
|
152 else: |
|
153 try: |
|
154 return self.__dict__[attr] |
|
155 except: |
|
156 raise AttributeError, attr |
|
157 |
|
158 def __mul__(self, other): |
|
159 raise TypeError, "bad operand type(s) for *" |
|
160 |
|
161 def __div__(self, other): |
|
162 raise TypeError, "bad operand type(s) for /" |
|
163 |
|
164 def strftime(self, format_string="%c"): |
|
165 "localtime([seconds]) -> (tm_year,tm_mon,tm_day,tm_hour,tm_min,tm_sec,tm_wday,tm_yday,tm_isdst)" |
|
166 # The map prevents a deprecation warning on Python 2.5.1 (Mac) |
|
167 # DeprecationWarning: integer argument expected, got float |
|
168 items = [int(item) for item in self.tuple()] |
|
169 return time.strftime(format_string, items) |
|
170 |
|
171 # Alias |
|
172 Format = strftime |
|
173 |
|
174 def tuple(self): |
|
175 return (self.year, self.month, self.day, self.hour, self.minute, |
|
176 self.second, self.day_of_week, self.day_of_year, -1) |
|
177 #return time.localtime(self.ticks()) |
|
178 |
|
179 def absvalues(self): |
|
180 return self.absdate, self.abstime |
|
181 |
|
182 def __float__(self): |
|
183 return self.ticks() |
|
184 |
|
185 def __int__(self): |
|
186 return int(self.ticks) |
|
187 |
|
188 def ticks(self, offset=0.0, dst=-1): |
|
189 tticks=time.mktime(self.year, self.month, self.day, self.hour, |
|
190 self.minute, self.second, self.day_of_week, 0, dst) |
|
191 if tticks == -1: |
|
192 raise OverflowError, "cannot convert value to a time value" |
|
193 ticks = (1.0*tticks) + (self.abstime - int(self.abstime)) - offset |
|
194 return ticks |
|
195 |
|
196 def gmticks(self, offset=0.0): |
|
197 from mx.DateTime import tz_offset |
|
198 return (self-tz_offset(self)).ticks() |
|
199 |
|
200 def gmtoffset(self): |
|
201 gmtime = DateTime(*time.gmtime()[:6]) |
|
202 return - (now() - gmtime) |
|
203 |
|
204 def __repr__(self): |
|
205 return "<DateTime object for '%d-%02d-%02d %02d:%02d:%05.2f' at %x>"% ( |
|
206 self.year, self.month, self.day, self.hour, self.minute, |
|
207 self.second, id(self)) |
|
208 |
|
209 def __cmp__(self, other, |
|
210 cmp=cmp): |
|
211 |
|
212 if isinstance(other,DateTime): |
|
213 cmpdate = cmp(self.absdate,other.absdate) |
|
214 if cmpdate == 0: |
|
215 return cmp(self.abstime,other.abstime) |
|
216 else: |
|
217 return cmpdate |
|
218 elif type(other) == types.NoneType: |
|
219 return -1 |
|
220 elif type(other) == types.StringType: |
|
221 return -1 |
|
222 elif type(other) in (types.FloatType, types.LongType, types.IntType): |
|
223 return 1 |
|
224 return -1 |
|
225 |
|
226 def __hash__(self): |
|
227 return hash(self.tuple()) |
|
228 |
|
229 def __add__(self, other): |
|
230 abstime=self.abstime |
|
231 absdate=self.absdate |
|
232 |
|
233 didadd=0 |
|
234 |
|
235 if type(other) == types.InstanceType: |
|
236 if other.__class__ == DateTimeDelta: |
|
237 abstime = abstime + other.seconds |
|
238 didadd=1 |
|
239 elif other.__class__ == DateTime: |
|
240 raise TypeError, "DateTime + DateTime is not supported" |
|
241 else: |
|
242 return other.__class__.__radd__(other, self) |
|
243 |
|
244 elif type(other) == types.IntType or type(other) == types.FloatType: |
|
245 abstime = abstime + other * 86400.0 |
|
246 didadd=1 |
|
247 |
|
248 if not didadd: |
|
249 raise TypeError, "cannot add these two types" |
|
250 |
|
251 if abstime >= 86400.0: |
|
252 days = abstime / 86400.0 |
|
253 absdate = absdate + days |
|
254 abstime = abstime - (86400.0 * int(days)) |
|
255 #print "absdate, abstime = ", absdate, abstime |
|
256 elif abstime < 0.0: |
|
257 days = int(((-abstime - 1) / 86400.0)) + 1 |
|
258 #days = int(-abstime / 86400.0) |
|
259 absdate = absdate - days |
|
260 abstime = abstime + 86400.0 * int(days) |
|
261 |
|
262 if absdate < 1: |
|
263 raise RangeError, "underflow while adding" |
|
264 |
|
265 return DateTimeFromAbsDateTime(absdate, abstime) |
|
266 |
|
267 def __radd__(self, other): |
|
268 return DateTime.__add__(other, self) |
|
269 |
|
270 def __sub__(self, other): |
|
271 abstime=self.abstime |
|
272 absdate=self.absdate |
|
273 |
|
274 didsub=0 |
|
275 if type(other) == types.InstanceType: |
|
276 if other.__class__ == DateTimeDelta: |
|
277 abstime = abstime - other.seconds |
|
278 didsub = 1 |
|
279 elif other.__class__ == DateTime: |
|
280 absdate = absdate - other.absdate |
|
281 abstime = abstime - other.abstime |
|
282 return DateTimeDelta(absdate,0.0,0.0,abstime) |
|
283 else: |
|
284 return other.__rsub__(self) |
|
285 |
|
286 elif type(other) == types.IntType or type(other) == types.FloatType: |
|
287 abstime = abstime - other * 86400.0; |
|
288 didsub=1 |
|
289 |
|
290 if not didsub: |
|
291 raise TypeError, "cannot subtract these two types" |
|
292 |
|
293 if abstime >= 86400.0: |
|
294 days = abstime / 86400.0 |
|
295 absdate = absdate + days |
|
296 abstime = abstime - (86400.0 * days) |
|
297 #print "absdate, abstime = ", absdate, abstime |
|
298 elif abstime < 0.0: |
|
299 #print "abstime < 0" |
|
300 days = int( ((-abstime - 1) / 86400.0) + 1) |
|
301 #days = -abstime / 86400.0 |
|
302 absdate = absdate - int(days) |
|
303 abstime = (1.0*abstime) + (86400.0 * days) |
|
304 #print "absdate, abstime", absdate, abstime |
|
305 if absdate < 1: |
|
306 raise RangeError, "underflow while adding" |
|
307 |
|
308 return DateTimeFromAbsDateTime(absdate, abstime) |
|
309 |
|
310 # Constants |
|
311 mjd0 = DateTime(1858, 11, 17) |
|
312 jdn0 = DateTime(-4713, 1, 1, 12, 0, 0.0) |
|
313 |
|
314 # Other DateTime constructors |
|
315 |
|
316 def DateTimeFromCOMDate(comdate): |
|
317 |
|
318 absdate = int(comdate) |
|
319 abstime = (comdate - float(absdate)) * 86400.0 |
|
320 if abstime < 0.0: |
|
321 abstime = -abstime |
|
322 absdate = absdate + 693594; |
|
323 dt = DateTimeFromAbsDateTime(absdate, abstime) |
|
324 dt.comdate = comdate |
|
325 return dt |
|
326 |
|
327 def DateTimeFromAbsDateTime(absdate, abstime): |
|
328 |
|
329 # Create the object without calling its default constructor |
|
330 dt = createEmptyObject(DateTime) |
|
331 |
|
332 # Init. the object |
|
333 abstime=1.0 * abstime |
|
334 if abstime < 0 and abstime > -0.001: abstime = 0.0 |
|
335 if not (absdate > 0): |
|
336 raise RangeError, "absdate out of range (>0)" |
|
337 if not (abstime >= 0.0 and abstime <= 86400.0): |
|
338 raise RangeError, "abstime out of range (0.0 - 86400.0) <%s>" % abstime |
|
339 |
|
340 dt.absdate=absdate |
|
341 dt.abstime=abstime |
|
342 |
|
343 #calculate com date |
|
344 comdate = 1.0 * (dt.absdate - 693594) |
|
345 if comdate < 0.0: |
|
346 comdate = comdate - dt.abstime / 86400.0 |
|
347 else: |
|
348 comdate = comdate + dt.abstime / 86400.0 |
|
349 dt.comdate = comdate |
|
350 |
|
351 #calculate the date |
|
352 #print "absdate=", absdate |
|
353 year = int((1.0 * absdate) / 365.2425) |
|
354 |
|
355 #newApproximation: |
|
356 while 1: |
|
357 #print "year=", year |
|
358 yearoffset = year * 365 + year / 4 - year / 100 + year / 400 |
|
359 #print "yearoffset=", yearoffset |
|
360 #print "absdate=", absdate |
|
361 if yearoffset >= absdate: |
|
362 year = year - 1 |
|
363 #print "year = ", year |
|
364 continue #goto newApproximation |
|
365 |
|
366 year = year + 1 |
|
367 leap = (year % 4 == 0) and ((year % 100 != 0) or (year % 400 == 0)) |
|
368 dayoffset = absdate - yearoffset |
|
369 #print "dayoffset=", dayoffset |
|
370 if dayoffset > 365 and leap == 0: |
|
371 #print "dayoffset=", dayoffset |
|
372 continue #goto newApproximation |
|
373 |
|
374 monthoffset = month_offset[leap] |
|
375 for month in range(1, 13): |
|
376 if monthoffset[month] >= dayoffset: |
|
377 break |
|
378 dt.year = year |
|
379 dt.month = month |
|
380 dt.day = dayoffset - month_offset[leap][month-1] |
|
381 dt.day_of_week = (dt.absdate - 1) % 7 |
|
382 dt.day_of_year = dayoffset |
|
383 break |
|
384 |
|
385 #calculate the time |
|
386 inttime = int(abstime) |
|
387 hour = inttime / 3600 |
|
388 minute = (inttime % 3600) / 60 |
|
389 second = abstime - 1.0 * (hour*3600 + minute*60) |
|
390 dt.hour = hour; |
|
391 dt.minute = minute; |
|
392 dt.second = second; |
|
393 dt.days_in_month = days_in_month[leap][month - 1] |
|
394 dt.dst = -1 |
|
395 dt.tz = "???" |
|
396 dt.is_leapyear = leap |
|
397 dt.yearoffset = yearoffset |
|
398 return dt |
|
399 |
|
400 def now( |
|
401 time=time.time,float=float,localtime=time.localtime, |
|
402 round=round,int=int,DateTime=DateTime,floor=math.floor): |
|
403 ticks = time() |
|
404 Y,M,D,h,m,s = localtime(ticks)[:6] |
|
405 s = s + (ticks - floor(ticks)) |
|
406 return DateTime(Y,M,D,h,m,s) |
|
407 |
|
408 def utc( |
|
409 time=time.time,float=float,gmtime=time.gmtime, |
|
410 round=round,int=int,DateTime=DateTime,floor=math.floor): |
|
411 |
|
412 ticks = time() |
|
413 Y,M,D,h,m,s = gmtime(ticks)[:6] |
|
414 s = s + (ticks - floor(ticks)) |
|
415 return DateTime(Y,M,D,h,m,s) |
|
416 |
|
417 # Aliases |
|
418 Date = Timestamp = DateTime |
|
419 |
|
420 # XXX Calendars are not supported: |
|
421 def notSupported(*args,**kws): |
|
422 raise Error,'calendars are not supported by the Python version of mxDateTime' |
|
423 JulianDateTime = notSupported |
|
424 |
|
425 ### DateTimeDelta class |
|
426 |
|
427 class DateTimeDelta: |
|
428 |
|
429 def __init__(self, days=0, hours=0, minutes=0, seconds=0): |
|
430 |
|
431 seconds = seconds + (days * 86400.0 + hours * 3600.0 + minutes * 60.0) |
|
432 self.seconds = seconds |
|
433 if seconds < 0.0: |
|
434 seconds = -seconds |
|
435 day = long(seconds / 86400.0) |
|
436 seconds = seconds - (86400.0 * day) |
|
437 wholeseconds = int(seconds) |
|
438 hour = wholeseconds / 3600 |
|
439 minute = (wholeseconds % 3600) / 60 |
|
440 second = seconds - (hour * 3600.0 + minute * 60.0) |
|
441 self.day = day |
|
442 self.hour = hour |
|
443 self.minute = minute |
|
444 self.second = second |
|
445 seconds=self.seconds |
|
446 self.minutes = seconds / 60.0 |
|
447 self.hours = seconds / 3600.0 |
|
448 self.days = seconds / 86400.0 |
|
449 |
|
450 def __str__(self): |
|
451 if self.day != 0: |
|
452 if self.seconds >= 0.0: |
|
453 r="%s:%02d:%02d:%05.2f" % ( |
|
454 self.day, self.hour, self.minute, self.second) |
|
455 else: |
|
456 r="-%s:%02d:%02d:%05.2f" % ( |
|
457 self.day, self.hour, self.minute, self.second) |
|
458 else: |
|
459 if self.seconds >= 0.0: |
|
460 r="%02d:%02d:%05.2f" % (self.hour, self.minute, self.second) |
|
461 else: |
|
462 r="-%02d:%02d:%05.2f" % (self.hour, self.minute, self.second) |
|
463 return r |
|
464 |
|
465 def absvalues(self): |
|
466 days=self.seconds / 86400 |
|
467 seconds=self.seconds - (days * 86400.0) |
|
468 return days, seconds |
|
469 |
|
470 def tuple(self): |
|
471 return (self.day, self.hour, self.minute, self.second) |
|
472 |
|
473 def strftime(self, format_string): |
|
474 raise NotImplementedError |
|
475 |
|
476 def __int__(self): |
|
477 return int(self.seconds) |
|
478 |
|
479 def __float__(self): |
|
480 return self.seconds |
|
481 |
|
482 def __cmp__(self, other, accuracy=0.0): |
|
483 if (type(other) == types.InstanceType |
|
484 and other.__class__ == DateTimeDelta): |
|
485 |
|
486 diff=self.seconds - other.seconds |
|
487 if abs(diff) > accuracy: |
|
488 if diff > 0: return 1 |
|
489 return -1 |
|
490 |
|
491 elif type(other) == types.FloatType: |
|
492 diff=self.seconds - other |
|
493 if abs(diff) > accuracy: |
|
494 if diff > 0: return 1 |
|
495 return -1 |
|
496 |
|
497 elif type(other) == types.IntType: |
|
498 diff=self.seconds - other |
|
499 if abs(diff) > accuracy: |
|
500 if diff > 0: return 1 |
|
501 return -1 |
|
502 |
|
503 return 0 |
|
504 |
|
505 def __getattr__(self, attr): |
|
506 seconds=self.__dict__['seconds'] |
|
507 if attr in ('hour', 'minute', 'second', 'day'): |
|
508 if seconds >= 0.0: |
|
509 return self.__dict__[attr] |
|
510 else: |
|
511 return -self.__dict__[attr] |
|
512 else: |
|
513 try: |
|
514 return self.__dict__[attr] |
|
515 except: |
|
516 raise AttributeError, attr |
|
517 |
|
518 def __div__(self, other): |
|
519 if type(other) in (types.IntType, types.FloatType): |
|
520 return DateTimeDelta(0.0,0.0,0.0,self.seconds / other) |
|
521 elif (type(other) == types.InstanceType |
|
522 and isinstance(other,DateTimeDelta)): |
|
523 return DateTimeDelta(0.0,0.0,0.0,self.seconds / other.seconds) |
|
524 raise TypeError, "bad operand types for /" |
|
525 |
|
526 def __mul__(self, other): |
|
527 if type(other) == types.IntType or type(other) == types.FloatType: |
|
528 return DateTimeDelta(0.0,0.0,0.0,self.seconds * other) |
|
529 else: |
|
530 #print "type", type(other) |
|
531 raise TypeError, "cannot multiply these two types" |
|
532 |
|
533 def __rmul__(self, other): |
|
534 return self.__mul__(other) |
|
535 |
|
536 def __neg__(self): |
|
537 return DateTimeDelta(0.0,0.0,0.0,-self.seconds) |
|
538 |
|
539 def __repr__(self): |
|
540 if self.day != 0: |
|
541 if self.seconds >= 0.0: |
|
542 strval="%s:%02d:%02d:%05.2f" % (self.day, self.hour, |
|
543 self.minute, self.second) |
|
544 else: |
|
545 strval="-%s:%02d:%02d:%05.2f" % (self.day, self.hour, |
|
546 self.minute, self.second) |
|
547 else: |
|
548 if self.seconds >= 0.0: |
|
549 strval="%02d:%02d:%05.2f" % (self.hour, self.minute, |
|
550 self.second) |
|
551 else: |
|
552 strval="-%02d:%02d:%05.2f" % (self.hour, self.minute, |
|
553 self.second) |
|
554 return "<DateTimeDelta object for '%s' at %x>" % (strval, id(self)) |
|
555 |
|
556 def __abs__(self): |
|
557 if self.seconds < 0: |
|
558 return -self |
|
559 return self |
|
560 |
|
561 def __nonzero__(self): |
|
562 return self.seconds != 0.0 |
|
563 |
|
564 def __add__(self, other): |
|
565 if type(other) == types.InstanceType: |
|
566 if isinstance(other,DateTime): |
|
567 return other + self |
|
568 elif isinstance(other,DateTimeDelta): |
|
569 return DateTimeDelta(0.0,0.0,0.0,self.seconds + other.seconds) |
|
570 |
|
571 # What about __radd__ ? |
|
572 |
|
573 # Other DateTimeDelta constructors |
|
574 |
|
575 def TimeDelta(hour=0.0, minute=0.0, second=0.0): |
|
576 return DateTimeDelta(0.0, hours, minutes, seconds) |
|
577 |
|
578 Time=TimeDelta |
|
579 |
|
580 def DateTimeDeltaFromSeconds(seconds): |
|
581 return DateTimeDelta(0.0,0.0,0.0,seconds) |
|
582 |
|
583 def DateTimeDeltaFromDays(days): |
|
584 return DateTimeDelta(days) |
|
585 |
|
586 ### Types |
|
587 |
|
588 DateTimeType = DateTime |
|
589 DateTimeDeltaType = DateTimeDelta |
|
590 |
|
591 ### Functions |
|
592 |
|
593 def cmp(a,b,acc): |
|
594 |
|
595 if isinstance(a,DateTime) and isinstance(b,DateTime): |
|
596 diff = a.absdays - b.absdays |
|
597 if (diff >= 0 and diff <= acc) or (diff < 0 and -diff <= acc): |
|
598 return 0 |
|
599 elif diff < 0: |
|
600 return 1 |
|
601 else: |
|
602 return -1 |
|
603 |
|
604 elif isinstance(a,DateTimeDelta) and isinstance(b,DateTimeDelta): |
|
605 diff = a.days - b.days |
|
606 if (diff >= 0 and diff <= acc) or (diff < 0 and -diff <= acc): |
|
607 return 0 |
|
608 elif diff < 0: |
|
609 return 1 |
|
610 else: |
|
611 return -1 |
|
612 |
|
613 else: |
|
614 raise TypeError,"objects must be DateTime[Delta] instances" |
|