comparison roundup/date.py @ 2388:8a9af227a557

Date and Interval objects allow to change translator after instance creation... ...and pass the translator to objects created by date arithmetics; remove unused import of module 'types'
author Alexander Smishlajev <a1s@users.sourceforge.net>
date Sat, 05 Jun 2004 12:04:02 +0000
parents 8611bf29baec
children 3953092900dd
comparison
equal deleted inserted replaced
2387:4962f99aaa27 2388:8a9af227a557
13 # BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 13 # BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
14 # FOR A PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" 14 # FOR A PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
15 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, 15 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
16 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 16 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
17 # 17 #
18 # $Id: date.py,v 1.70 2004-05-23 10:23:28 richard Exp $ 18 # $Id: date.py,v 1.71 2004-06-05 12:04:02 a1s Exp $
19 19
20 """Date, time and time interval handling. 20 """Date, time and time interval handling.
21 """ 21 """
22 __docformat__ = 'restructuredtext' 22 __docformat__ = 'restructuredtext'
23 23
24 import time, re, calendar, types 24 import time, re, calendar
25 from types import * 25 from types import *
26 import i18n 26 import i18n
27 27
28 def _add_granularity(src, order, value = 1): 28 def _add_granularity(src, order, value = 1):
29 '''Increment first non-None value in src dictionary ordered by 'order' 29 '''Increment first non-None value in src dictionary ordered by 'order'
120 'translator' 120 'translator'
121 is i18n module or one of gettext translation classes. 121 is i18n module or one of gettext translation classes.
122 It must have attributes 'gettext' and 'ngettext', 122 It must have attributes 'gettext' and 'ngettext',
123 serving as translation functions. 123 serving as translation functions.
124 """ 124 """
125 self._ = translator.gettext 125 self.setTranslator(translator)
126 self.ngettext = translator.ngettext
127 if type(spec) == type(''): 126 if type(spec) == type(''):
128 self.set(spec, offset=offset, add_granularity=add_granularity) 127 self.set(spec, offset=offset, add_granularity=add_granularity)
129 return 128 return
130 elif hasattr(spec, 'tuple'): 129 elif hasattr(spec, 'tuple'):
131 spec = spec.tuple() 130 spec = spec.tuple()
282 self.second, x, x, x = self.addInterval(interval) 281 self.second, x, x, x = self.addInterval(interval)
283 282
284 def __add__(self, interval): 283 def __add__(self, interval):
285 """Add an interval to this date to produce another date. 284 """Add an interval to this date to produce another date.
286 """ 285 """
287 return Date(self.addInterval(interval)) 286 return Date(self.addInterval(interval), translator=self.translator)
288 287
289 # deviates from spec to allow subtraction of dates as well 288 # deviates from spec to allow subtraction of dates as well
290 def __sub__(self, other): 289 def __sub__(self, other):
291 """ Subtract: 290 """ Subtract:
292 1. an interval from this date to produce another date. 291 1. an interval from this date to produce another date.
320 diff = -diff 319 diff = -diff
321 S = diff%60 320 S = diff%60
322 M = (diff/60)%60 321 M = (diff/60)%60
323 H = (diff/(60*60))%24 322 H = (diff/(60*60))%24
324 d = diff/(24*60*60) 323 d = diff/(24*60*60)
325 return Interval((0, 0, d, H, M, S), sign=sign) 324 return Interval((0, 0, d, H, M, S), sign=sign,
325 translator=self.translator)
326 326
327 def __cmp__(self, other, int_seconds=0): 327 def __cmp__(self, other, int_seconds=0):
328 """Compare this date to another date.""" 328 """Compare this date to another date."""
329 if other is None: 329 if other is None:
330 return 1 330 return 1
366 366
367 def local(self, offset): 367 def local(self, offset):
368 """ Return this date as yyyy-mm-dd.hh:mm:ss in a local time zone. 368 """ Return this date as yyyy-mm-dd.hh:mm:ss in a local time zone.
369 """ 369 """
370 return Date((self.year, self.month, self.day, self.hour + offset, 370 return Date((self.year, self.month, self.day, self.hour + offset,
371 self.minute, self.second, 0, 0, 0)) 371 self.minute, self.second, 0, 0, 0), translator=self.translator)
372 372
373 def __deepcopy__(self, memo): 373 def __deepcopy__(self, memo):
374 return Date((self.year, self.month, self.day, self.hour, 374 return Date((self.year, self.month, self.day, self.hour,
375 self.minute, self.second, 0, 0, 0)) 375 self.minute, self.second, 0, 0, 0), translator=self.translator)
376 376
377 def get_tuple(self): 377 def get_tuple(self):
378 return (self.year, self.month, self.day, self.hour, self.minute, 378 return (self.year, self.month, self.day, self.hour, self.minute,
379 self.second, 0, 0, 0) 379 self.second, 0, 0, 0)
380 380
387 frac = self.second - int(self.second) 387 frac = self.second - int(self.second)
388 ts = calendar.timegm((self.year, self.month, self.day, self.hour, 388 ts = calendar.timegm((self.year, self.month, self.day, self.hour,
389 self.minute, self.second, 0, 0, 0)) 389 self.minute, self.second, 0, 0, 0))
390 # we lose the fractional part 390 # we lose the fractional part
391 return ts + frac 391 return ts + frac
392
393 def setTranslator(self, translator):
394 """Replace the translation engine
395
396 'translator'
397 is i18n module or one of gettext translation classes.
398 It must have attributes 'gettext' and 'ngettext',
399 serving as translation functions.
400 """
401 self.translator = translator
402 self._ = translator.gettext
403 self.ngettext = translator.ngettext
392 404
393 class Interval: 405 class Interval:
394 ''' 406 '''
395 Date intervals are specified using the suffixes "y", "m", and "d". The 407 Date intervals are specified using the suffixes "y", "m", and "d". The
396 suffix "w" (for "week") means 7 days. Time intervals are specified in 408 suffix "w" (for "week") means 7 days. Time intervals are specified in
444 ''' 456 '''
445 def __init__(self, spec, sign=1, allowdate=1, add_granularity=0, 457 def __init__(self, spec, sign=1, allowdate=1, add_granularity=0,
446 translator=i18n 458 translator=i18n
447 ): 459 ):
448 """Construct an interval given a specification.""" 460 """Construct an interval given a specification."""
449 self._ = translator.gettext 461 self.setTranslator(translator)
450 self.ngettext = translator.ngettext
451 if type(spec) in (IntType, FloatType, LongType): 462 if type(spec) in (IntType, FloatType, LongType):
452 self.from_seconds(spec) 463 self.from_seconds(spec)
453 elif type(spec) in (StringType, UnicodeType): 464 elif type(spec) in (StringType, UnicodeType):
454 self.set(spec, allowdate=allowdate, add_granularity=add_granularity) 465 self.set(spec, allowdate=allowdate, add_granularity=add_granularity)
455 else: 466 else:
464 self.second = spec 475 self.second = spec
465 self.second = int(self.second) 476 self.second = int(self.second)
466 477
467 def __deepcopy__(self, memo): 478 def __deepcopy__(self, memo):
468 return Interval((self.sign, self.year, self.month, self.day, 479 return Interval((self.sign, self.year, self.month, self.day,
469 self.hour, self.minute, self.second)) 480 self.hour, self.minute, self.second), translator=self.translator)
470 481
471 def set(self, spec, allowdate=1, interval_re=re.compile(''' 482 def set(self, spec, allowdate=1, interval_re=re.compile('''
472 \s*(?P<s>[-+])? # + or - 483 \s*(?P<s>[-+])? # + or -
473 \s*((?P<y>\d+\s*)y)? # year 484 \s*((?P<y>\d+\s*)y)? # year
474 \s*((?P<m>\d+\s*)m)? # month 485 \s*((?P<m>\d+\s*)m)? # month
559 return ' '.join(l) 570 return ' '.join(l)
560 571
561 def __add__(self, other): 572 def __add__(self, other):
562 if isinstance(other, Date): 573 if isinstance(other, Date):
563 # the other is a Date - produce a Date 574 # the other is a Date - produce a Date
564 return Date(other.addInterval(self)) 575 return Date(other.addInterval(self), translator=self.translator)
565 elif isinstance(other, Interval): 576 elif isinstance(other, Interval):
566 # add the other Interval to this one 577 # add the other Interval to this one
567 a = self.get_tuple() 578 a = self.get_tuple()
568 as = a[0] 579 as = a[0]
569 b = other.get_tuple() 580 b = other.get_tuple()
570 bs = b[0] 581 bs = b[0]
571 i = [as*x + bs*y for x,y in zip(a[1:],b[1:])] 582 i = [as*x + bs*y for x,y in zip(a[1:],b[1:])]
572 i.insert(0, 1) 583 i.insert(0, 1)
573 i = fixTimeOverflow(i) 584 i = fixTimeOverflow(i)
574 return Interval(i) 585 return Interval(i, translator=self.translator)
575 # nope, no idea what to do with this other... 586 # nope, no idea what to do with this other...
576 raise TypeError, "Can't add %r"%other 587 raise TypeError, "Can't add %r"%other
577 588
578 def __sub__(self, other): 589 def __sub__(self, other):
579 if isinstance(other, Date): 590 if isinstance(other, Date):
580 # the other is a Date - produce a Date 591 # the other is a Date - produce a Date
581 interval = Interval(self.get_tuple()) 592 interval = Interval(self.get_tuple())
582 interval.sign *= -1 593 interval.sign *= -1
583 return Date(other.addInterval(interval)) 594 return Date(other.addInterval(interval),
595 translator=self.translator)
584 elif isinstance(other, Interval): 596 elif isinstance(other, Interval):
585 # add the other Interval to this one 597 # add the other Interval to this one
586 a = self.get_tuple() 598 a = self.get_tuple()
587 as = a[0] 599 as = a[0]
588 b = other.get_tuple() 600 b = other.get_tuple()
589 bs = b[0] 601 bs = b[0]
590 i = [as*x - bs*y for x,y in zip(a[1:],b[1:])] 602 i = [as*x - bs*y for x,y in zip(a[1:],b[1:])]
591 i.insert(0, 1) 603 i.insert(0, 1)
592 i = fixTimeOverflow(i) 604 i = fixTimeOverflow(i)
593 return Interval(i) 605 return Interval(i, translator=self.translator)
594 # nope, no idea what to do with this other... 606 # nope, no idea what to do with this other...
595 raise TypeError, "Can't add %r"%other 607 raise TypeError, "Can't add %r"%other
596 608
597 def __div__(self, other): 609 def __div__(self, other):
598 """ Divide this interval by an int value. 610 """ Divide this interval by an int value.
616 months = int(months/other) 628 months = int(months/other)
617 629
618 sign = months<0 and -1 or 1 630 sign = months<0 and -1 or 1
619 m = months%12 631 m = months%12
620 y = months / 12 632 y = months / 12
621 return Interval((sign, y, m, 0, 0, 0, 0)) 633 return Interval((sign, y, m, 0, 0, 0, 0),
634 translator=self.translator)
622 635
623 else: 636 else:
624 # handle a day/time division 637 # handle a day/time division
625 seconds = S + M*60 + H*60*60 + d*60*60*24 638 seconds = S + M*60 + H*60*60 + d*60*60*24
626 seconds *= self.sign 639 seconds *= self.sign
633 seconds /= 60 646 seconds /= 60
634 M = seconds%60 647 M = seconds%60
635 seconds /= 60 648 seconds /= 60
636 H = seconds%24 649 H = seconds%24
637 d = seconds / 24 650 d = seconds / 24
638 return Interval((sign, 0, 0, d, H, M, S)) 651 return Interval((sign, 0, 0, d, H, M, S),
652 translator=self.translator)
639 653
640 def __repr__(self): 654 def __repr__(self):
641 return '<Interval %s>'%self.__str__() 655 return '<Interval %s>'%self.__str__()
642 656
643 def pretty(self): 657 def pretty(self):
742 self.hour = val % 24 756 self.hour = val % 24
743 val = val / 24 757 val = val / 24
744 self.day = val 758 self.day = val
745 self.month = self.year = 0 759 self.month = self.year = 0
746 760
761 def setTranslator(self, translator):
762 """Replace the translation engine
763
764 'translator'
765 is i18n module or one of gettext translation classes.
766 It must have attributes 'gettext' and 'ngettext',
767 serving as translation functions.
768 """
769 self.translator = translator
770 self._ = translator.gettext
771 self.ngettext = translator.ngettext
772
747 773
748 def fixTimeOverflow(time): 774 def fixTimeOverflow(time):
749 """ Handle the overflow in the time portion (H, M, S) of "time": 775 """ Handle the overflow in the time portion (H, M, S) of "time":
750 (sign, y,m,d,H,M,S) 776 (sign, y,m,d,H,M,S)
751 777

Roundup Issue Tracker: http://roundup-tracker.org/