Mercurial > p > roundup > code
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 |
