Code

Added 'Users may only edit their issues' customisation example.
[roundup.git] / roundup / date.py
index 365aa80b07cc670a641400ea896e0f9a753f8cd0..49151768aedaf563b78e76c689702609803b671d 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.54 2003-04-23 11:48:05 richard Exp $
+# $Id: date.py,v 1.59 2003-12-05 03:28:38 richard Exp $
 
 __doc__ = """
 Date, time and time interval handling.
@@ -190,13 +190,13 @@ class Date:
         # now cope with under- and over-flow
         # first do the time
         while (second < 0 or second > 59 or minute < 0 or minute > 59 or
-                hour < 0 or hour > 59):
+                hour < 0 or hour > 23):
             if second < 0: minute -= 1; second += 60
             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 += 24
-            elif hour > 59: day += 1; hour -= 24
+            elif hour > 23: day += 1; hour -= 24
 
         # fix up the month so we're within range
         while month < 1 or month > 12:
@@ -204,24 +204,31 @@ class Date:
             if month > 12: year += 1; month -= 12
 
         # now do the days, now that we know what month we're in
-        mdays = calendar.mdays
-        if month == 2 and calendar.isleap(year): month_days = 29
-        else: month_days = mdays[month]
-        while month < 1 or month > 12 or day < 0 or day > month_days:
+        def get_mdays(year, month):
+            if month == 2 and calendar.isleap(year): return 29
+            else: return calendar.mdays[month]
+
+        while month < 1 or month > 12 or day < 1 or day > get_mdays(year,month):
             # now to day under/over
-            if day < 0: month -= 1; day += month_days
-            elif day > month_days: month += 1; day -= month_days
+            if day < 1: 
+                # When going backwards, decrement month, then increment days
+                month -= 1
+                day += get_mdays(year,month)
+            elif day > get_mdays(year,month): 
+                # When going forwards, decrement days, then increment month
+                day -= get_mdays(year,month)
+                month += 1
 
             # possibly fix up the month so we're within range
             while month < 1 or month > 12:
-                if month < 1: year -= 1; month += 12
+                if month < 1: year -= 1; month += 12 ; day += 31
                 if month > 12: year += 1; month -= 12
 
-            # 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)
 
+    def differenceDate(self, other):
+        "Return the difference between this date and another date"
+
     def applyInterval(self, interval):
         ''' Apply the interval to this date
         '''
@@ -246,29 +253,29 @@ class Date:
 
         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, ....
+        return self.dateDelta(other)
+
+    def dateDelta(self, other):
+        """ Produce an Interval of the difference between this date
+            and another date. Only returns days:hours:minutes:seconds.
+        """
+        # Returning intervals larger than a day is almost
+        # impossible - months, years, weeks, are all so imprecise.
         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:
+        if diff > 0:
             sign = 1
-            diff = -diff
         else:
             sign = -1
+            diff = -diff
         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)
+        H = (diff/(60*60))%24
+        d = diff/(24*60*60)
+        return Interval((0, 0, d, H, M, S), sign=sign)
 
     def __cmp__(self, other):
         """Compare this date to another date."""
@@ -316,6 +323,11 @@ class Date:
         return '%4d%02d%02d%02d%02d%02d'%(self.year, self.month,
             self.day, self.hour, self.minute, self.second)
 
+    def timestamp(self):
+        ''' return a UNIX timestamp for this date '''
+        return calendar.timegm((self.year, self.month, self.day, self.hour,
+            self.minute, self.second, 0, 0, 0))
+
 class Interval:
     '''
     Date intervals are specified using the suffixes "y", "m", and "d". The
@@ -507,11 +519,11 @@ class Interval:
         raise TypeError, "Can't add %r"%other
 
     def __div__(self, other):
-        ''' Divide this interval by an int value.
+        """ Divide this interval by an int value.
 
             Can't divide years and months sensibly in the _same_
             calculation as days/time, so raise an error in that situation.
-        '''
+        """
         try:
             other = float(other)
         except TypeError:
@@ -557,9 +569,9 @@ class Interval:
         '''
         if self.year:
             if self.year == 1:
-                return _('1 year')
+                s = _('1 year')
             else:
-                return _('%(number)s years')%{'number': self.year}
+                s = _('%(number)s years')%{'number': self.year}
         elif self.month or self.day > 13:
             days = (self.month * 30) + self.day
             if days > 28:
@@ -616,13 +628,13 @@ class Interval:
             self.day, self.hour, self.minute, self.second)
 
 def fixTimeOverflow(time):
-    ''' Handle the overflow in the time portion (H, M, S) of "time":
+    """ Handle the overflow in the time portion (H, M, S) of "time":
             (sign, y,m,d,H,M,S)
 
         Overflow and underflow will at most affect the _days_ portion of
         the date. We do not overflow days to months as we don't know _how_
         to, generally.
-    '''
+    """
     # XXX we could conceivably use this function for handling regular dates
     # XXX too - we just need to interrogate the month/year for the day
     # XXX overflow...