Code

grant web access to admin ;)
[roundup.git] / roundup / date.py
index c707e6830d96f408149720c8dbea582fb9159293..a7f212a553c0ca3c15a9a96db610c37afe49beb6 100644 (file)
@@ -15,7 +15,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: date.py,v 1.19 2002-02-21 23:11:45 richard Exp $
+# $Id: date.py,v 1.23 2002-07-18 23:07:08 richard Exp $
 
 __doc__ = """
 Date, time and time interval handling.
@@ -91,29 +91,17 @@ class Date:
             self.year, self.month, self.day, self.hour, self.minute, \
                 self.second, x, x, x = time.gmtime(ts)
 
-    def applyInterval(self, interval):
-        ''' Apply the interval to this date
+    def addInterval(self, interval):
+        ''' Add the interval to this date, returning the date tuple
         '''
-        t = (self.year + interval.year,
-             self.month + interval.month,
-             self.day + interval.day,
-             self.hour + interval.hour,
-             self.minute + interval.minute,
-             self.second + interval.second, 0, 0, 0)
-        self.year, self.month, self.day, self.hour, self.minute, \
-            self.second, x, x, x = time.gmtime(calendar.timegm(t))
-
-    def __add__(self, other):
-        """Add an interval to this date to produce another date.
-        """
         # do the basic calc
-        sign = other.sign
-        year = self.year + sign * other.year
-        month = self.month + sign * other.month
-        day = self.day + sign * other.day
-        hour = self.hour + sign * other.hour
-        minute = self.minute + sign * other.minute
-        second = self.second + sign * other.second
+        sign = interval.sign
+        year = self.year + sign * interval.year
+        month = self.month + sign * interval.month
+        day = self.day + sign * interval.day
+        hour = self.hour + sign * interval.hour
+        minute = self.minute + sign * interval.minute
+        second = self.second + sign * interval.second
 
         # now cope with under- and over-flow
         # first do the time
@@ -123,8 +111,8 @@ class Date:
             elif second > 59: minute += 1; second -= 60
             if minute < 0: hour -= 1; minute += 60
             elif minute > 59: hour += 1; minute -= 60
-            if hour < 0: day -= 1; hour += 60
-            elif hour > 59: day += 1; hour -= 60
+            if hour < 0: day -= 1; hour += 24
+            elif hour > 59: day += 1; hour -= 24
 
         # fix up the month so we're within range
         while month < 1 or month > 12:
@@ -148,8 +136,18 @@ class Date:
             # re-figure the number of days for this month
             if month == 2 and calendar.isleap(year): month_days = 29
             else: month_days = mdays[month]
+        return (year, month, day, hour, minute, second, 0, 0, 0)
 
-        return Date((year, month, day, hour, minute, second, 0, 0, 0))
+    def applyInterval(self, interval):
+        ''' Apply the interval to this date
+        '''
+        self.year, self.month, self.day, self.hour, self.minute, \
+            self.second, x, x, x = self.addInterval(interval)
+
+    def __add__(self, interval):
+        """Add an interval to this date to produce another date.
+        """
+        return Date(self.addInterval(interval))
 
     # XXX deviates from spec to allow subtraction of dates as well
     def __sub__(self, other):
@@ -157,37 +155,43 @@ class Date:
              1. an interval from this date to produce another date.
              2. a date from this date to produce an interval.
         """
-        if isinstance(other, Date):
-            # TODO this code will fall over laughing if the dates cross
-            # leap years, phases of the moon, ....
-            a = calendar.timegm((self.year, self.month, self.day, self.hour,
-                self.minute, self.second, 0, 0, 0))
-            b = calendar.timegm((other.year, other.month, other.day,
-                other.hour, other.minute, other.second, 0, 0, 0))
-            diff = a - b
-            if diff < 0:
-                sign = 1
-                diff = -diff
-            else:
-                sign = -1
-            S = diff%60
-            M = (diff/60)%60
-            H = (diff/(60*60))%60
-            if H>1: S = 0
-            d = (diff/(24*60*60))%30
-            if d>1: H = S = M = 0
-            m = (diff/(30*24*60*60))%12
-            if m>1: H = S = M = 0
-            y = (diff/(365*24*60*60))
-            if y>1: d = H = S = M = 0
-            return Interval((y, m, d, H, M, S), sign=sign)
-        return self.__add__(other)
+        if isinstance(other, Interval):
+            other = Interval(other.get_tuple(), sign=-other.sign)
+            return self.__add__(other)
+
+        assert isinstance(other, Date), 'May only subtract Dates or Intervals'
+
+        # TODO this code will fall over laughing if the dates cross
+        # leap years, phases of the moon, ....
+        a = calendar.timegm((self.year, self.month, self.day, self.hour,
+            self.minute, self.second, 0, 0, 0))
+        b = calendar.timegm((other.year, other.month, other.day,
+            other.hour, other.minute, other.second, 0, 0, 0))
+        diff = a - b
+        if diff < 0:
+            sign = 1
+            diff = -diff
+        else:
+            sign = -1
+        S = diff%60
+        M = (diff/60)%60
+        H = (diff/(60*60))%60
+        if H>1: S = 0
+        d = (diff/(24*60*60))%30
+        if d>1: H = S = M = 0
+        m = (diff/(30*24*60*60))%12
+        if m>1: H = S = M = 0
+        y = (diff/(365*24*60*60))
+        if y>1: d = H = S = M = 0
+        return Interval((y, m, d, H, M, S), sign=sign)
 
     def __cmp__(self, other):
         """Compare this date to another date."""
         if other is None:
             return 1
         for attr in ('year', 'month', 'day', 'hour', 'minute', 'second'):
+            if not hasattr(other, attr):
+                return 1
             r = cmp(getattr(self, attr), getattr(other, attr))
             if r: return r
         return 0
@@ -302,6 +306,8 @@ class Interval:
         if other is None:
             return 1
         for attr in ('year', 'month', 'day', 'hour', 'minute', 'second'):
+            if not hasattr(other, attr):
+                return 1
             r = cmp(getattr(self, attr), getattr(other, attr))
             if r: return r
         return 0
@@ -362,8 +368,11 @@ class Interval:
     def pretty(self):
         ''' print up the date date using one of these nice formats..
         '''
-        if self.year or self.month > 2:
-            return None
+        if self.year:
+            if self.year == 1:
+                return _('1 year')
+            else:
+                return _('%(number)s years')%{'number': self.year}
         elif self.month or self.day > 13:
             days = (self.month * 30) + self.day
             if days > 28:
@@ -433,6 +442,21 @@ if __name__ == '__main__':
 
 #
 # $Log: not supported by cvs2svn $
+# Revision 1.22  2002/07/14 06:05:50  richard
+#  . fixed the date module so that Date(". - 2d") works
+#
+# Revision 1.21  2002/05/15 06:32:46  richard
+#  . reverting to dates for intervals > 2 months sucks
+#
+# Revision 1.20  2002/02/21 23:34:51  richard
+# Oops, there's 24 hours in a day, and subtraction of intervals now works
+# properly.
+#
+# Revision 1.19  2002/02/21 23:11:45  richard
+#  . fixed some problems in date calculations (calendar.py doesn't handle over-
+#    and under-flow). Also, hour/minute/second intervals may now be more than
+#    99 each.
+#
 # Revision 1.18  2002/01/23 20:00:50  jhermann
 # %e is a UNIXism and not documented for Python
 #