From: richard Date: Wed, 19 Mar 2003 03:25:30 +0000 (+0000) Subject: fixed detection of bad date specs (sf bug 691439) X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=3cd572b9843d1cc2a9b3baf865a72e21cb76a598;p=roundup.git fixed detection of bad date specs (sf bug 691439) git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@1607 57a73879-2fb5-44c3-a270-3262357dd7e2 --- diff --git a/CHANGES.txt b/CHANGES.txt index f8baa3a..8a3ae62 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -77,6 +77,7 @@ Fixed: - fixed Interval maths (sf bug 665357) - fixed sqlite rollback/caching bug (sf bug 689383) - fixed rdbms table update detection logic (sf bug 703297) +- fixed detection of bad date specs (sf bug 691439) 2003-02-27 0.5.6 diff --git a/roundup/date.py b/roundup/date.py index da341c6..2654a03 100644 --- a/roundup/date.py +++ b/roundup/date.py @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: date.py,v 1.48 2003-03-10 20:32:53 kedder Exp $ +# $Id: date.py,v 1.49 2003-03-19 03:25:30 richard Exp $ __doc__ = """ Date, time and time interval handling. @@ -95,6 +95,63 @@ class Date: self.year, self.month, self.day, self.hour, self.minute, \ self.second, x, x, x = time.gmtime(ts) + def set(self, spec, offset=0, date_re=re.compile(r''' + (((?P\d\d\d\d)-)?(?P\d\d?)?-(?P\d\d?))? # [yyyy-]mm-dd + (?P\.)? # . + (((?P\d?\d):(?P\d\d))?(:(?P\d\d))?)? # hh:mm:ss + (?P.+)? # offset + ''', re.VERBOSE), serialised_re=re.compile(r''' + (\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d) + ''', re.VERBOSE)): + ''' set the date to the value in spec + ''' + m = serialised_re.match(spec) + if m is not None: + # we're serialised - easy! + self.year, self.month, self.day, self.hour, self.minute, \ + self.second = map(int, m.groups()[:6]) + return + + # not serialised data, try usual format + m = date_re.match(spec) + if m is None: + raise ValueError, _('Not a date spec: [[yyyy-]mm-dd].' + '[[h]h:mm[:ss]][offset]') + + info = m.groupdict() + + # get the current date as our default + y,m,d,H,M,S,x,x,x = time.gmtime(time.time()) + + # override year, month, day parts + if info['m'] is not None and info['d'] is not None: + m = int(info['m']) + d = int(info['d']) + if info['y'] is not None: + y = int(info['y']) + # time defaults to 00:00:00 GMT - offset (local midnight) + H = -offset + M = S = 0 + + # override hour, minute, second parts + if info['H'] is not None and info['M'] is not None: + H = int(info['H']) - offset + M = int(info['M']) + S = 0 + if info['S'] is not None: S = int(info['S']) + + # now handle the adjustment of hour + ts = calendar.timegm((y,m,d,H,M,S,0,0,0)) + self.year, self.month, self.day, self.hour, self.minute, \ + self.second, x, x, x = time.gmtime(ts) + + if info.get('o', None): + try: + self.applyInterval(Interval(info['o'])) + except ValueError: + raise ValueError, _('Not a date spec: [[yyyy-]mm-dd].' + '[[h]h:mm[:ss]][offset]') + def addInterval(self, interval): ''' Add the interval to this date, returning the date tuple ''' @@ -219,59 +276,6 @@ class Date: return ' ' + str[1:] return str - def set(self, spec, offset=0, date_re=re.compile(r''' - (((?P\d\d\d\d)-)?((?P\d\d?)-(?P\d\d?))?)? # yyyy-mm-dd - (?P\.)? # . - (((?P\d?\d):(?P\d\d))?(:(?P\d\d))?)? # hh:mm:ss - (?P.+)? # offset - ''', re.VERBOSE), serialised_re=re.compile(r''' - (\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d) - ''', re.VERBOSE)): - ''' set the date to the value in spec - ''' - m = serialised_re.match(spec) - if m is not None: - # we're serialised - easy! - self.year, self.month, self.day, self.hour, self.minute, \ - self.second = map(int, m.groups()[:6]) - return - - # not serialised data, try usual format - m = date_re.match(spec) - if m is None: - raise ValueError, _('Not a date spec: [[yyyy-]mm-dd].' - '[[h]h:mm[:ss]][offset]') - - info = m.groupdict() - - # get the current date as our default - y,m,d,H,M,S,x,x,x = time.gmtime(time.time()) - - # override year, month, day parts - if info['m'] is not None and info['d'] is not None: - m = int(info['m']) - d = int(info['d']) - if info['y'] is not None: - y = int(info['y']) - # time defaults to 00:00:00 GMT - offset (local midnight) - H = -offset - M = S = 0 - - # override hour, minute, second parts - if info['H'] is not None and info['M'] is not None: - H = int(info['H']) - offset - M = int(info['M']) - S = 0 - if info['S'] is not None: S = int(info['S']) - - # now handle the adjustment of hour - ts = calendar.timegm((y,m,d,H,M,S,0,0,0)) - self.year, self.month, self.day, self.hour, self.minute, \ - self.second, x, x, x = time.gmtime(ts) - - if info.get('o', None): - self.applyInterval(Interval(info['o'])) - def __repr__(self): return ''%self.__str__() @@ -351,6 +355,46 @@ class Interval: self.year, self.month, self.day, self.hour, self.minute, \ self.second = spec + def set(self, spec, interval_re=re.compile(''' + \s*(?P[-+])? # + or - + \s*((?P\d+\s*)y)? # year + \s*((?P\d+\s*)m)? # month + \s*((?P\d+\s*)w)? # week + \s*((?P\d+\s*)d)? # day + \s*(((?P\d+):(?P\d+))?(:(?P\d+))?)? # time + \s*''', re.VERBOSE), serialised_re=re.compile(''' + (?P[+-])?1?(?P([ ]{3}\d|\d{4}))(?P\d{2})(?P\d{2}) + (?P\d{2})(?P\d{2})(?P\d{2})''', re.VERBOSE)): + ''' set the date to the value in spec + ''' + self.year = self.month = self.week = self.day = self.hour = \ + self.minute = self.second = 0 + self.sign = 1 + m = serialised_re.match(spec) + if not m: + m = interval_re.match(spec) + if not m: + raise ValueError, _('Not an interval spec: [+-] [#y] [#m] [#w] ' + '[#d] [[[H]H:MM]:SS]') + + info = m.groupdict() + valid = 0 + for group, attr in {'y':'year', 'm':'month', 'w':'week', 'd':'day', + 'H':'hour', 'M':'minute', 'S':'second'}.items(): + if info.get(group, None) is not None: + valid = 1 + setattr(self, attr, int(info[group])) + + if not valid: + raise ValueError, _('Not an interval spec: [+-] [#y] [#m] [#w] ' + '[#d] [[[H]H:MM]:SS]') + + if self.week: + self.day = self.day + self.week*7 + + if info['s'] is not None: + self.sign = {'+':1, '-':-1}[info['s']] + def __cmp__(self, other): """Compare this interval to another interval.""" if other is None: @@ -455,40 +499,6 @@ class Interval: d = seconds / 24 return Interval((sign, 0, 0, d, H, M, S)) - def set(self, spec, interval_re=re.compile(''' - \s*(?P[-+])? # + or - - \s*((?P\d+\s*)y)? # year - \s*((?P\d+\s*)m)? # month - \s*((?P\d+\s*)w)? # week - \s*((?P\d+\s*)d)? # day - \s*(((?P\d+):(?P\d+))?(:(?P\d+))?)? # time - \s*''', re.VERBOSE), serialised_re=re.compile(''' - (?P[+-])?1?(?P([ ]{3}\d|\d{4}))(?P\d{2})(?P\d{2}) - (?P\d{2})(?P\d{2})(?P\d{2})''', re.VERBOSE)): - ''' set the date to the value in spec - ''' - self.year = self.month = self.week = self.day = self.hour = \ - self.minute = self.second = 0 - self.sign = 1 - m = serialised_re.match(spec) - if not m: - m = interval_re.match(spec) - if not m: - raise ValueError, _('Not an interval spec: [+-] [#y] [#m] [#w] ' - '[#d] [[[H]H:MM]:SS]') - - info = m.groupdict() - for group, attr in {'y':'year', 'm':'month', 'w':'week', 'd':'day', - 'H':'hour', 'M':'minute', 'S':'second'}.items(): - if info.get(group, None) is not None: - setattr(self, attr, int(info[group])) - - if self.week: - self.day = self.day + self.week*7 - - if info['s'] is not None: - self.sign = {'+':1, '-':-1}[info['s']] - def __repr__(self): return ''%self.__str__() diff --git a/test/test_dates.py b/test/test_dates.py index fc0c9bd..44f3f10 100644 --- a/test/test_dates.py +++ b/test/test_dates.py @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: test_dates.py,v 1.20 2003-03-10 00:22:21 richard Exp $ +# $Id: test_dates.py,v 1.21 2003-03-19 03:25:30 richard Exp $ import unittest, time @@ -53,6 +53,9 @@ class DateTestCase(unittest.TestCase): date = Date("8:47:11") ae(str(date), '%s-%02d-%02d.08:47:11'%(y, m, d)) + def testDateError(self): + self.assertRaises(ValueError, Date, "12") + def testOffset(self): ae = self.assertEqual date = Date("2000-04-17", -5)