Skip to content

Commit 2559279

Browse files
author
Richard Jones
committed
fixed detection of bad date specs [SF#691439]
1 parent 41e5400 commit 2559279

File tree

3 files changed

+103
-89
lines changed

3 files changed

+103
-89
lines changed

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ Fixed:
7777
- fixed Interval maths (sf bug 665357)
7878
- fixed sqlite rollback/caching bug (sf bug 689383)
7979
- fixed rdbms table update detection logic (sf bug 703297)
80+
- fixed detection of bad date specs (sf bug 691439)
8081

8182

8283
2003-02-27 0.5.6

roundup/date.py

Lines changed: 98 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
1616
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
1717
#
18-
# $Id: date.py,v 1.48 2003-03-10 20:32:53 kedder Exp $
18+
# $Id: date.py,v 1.49 2003-03-19 03:25:30 richard Exp $
1919

2020
__doc__ = """
2121
Date, time and time interval handling.
@@ -95,6 +95,63 @@ def __init__(self, spec='.', offset=0):
9595
self.year, self.month, self.day, self.hour, self.minute, \
9696
self.second, x, x, x = time.gmtime(ts)
9797

98+
def set(self, spec, offset=0, date_re=re.compile(r'''
99+
(((?P<y>\d\d\d\d)-)?(?P<m>\d\d?)?-(?P<d>\d\d?))? # [yyyy-]mm-dd
100+
(?P<n>\.)? # .
101+
(((?P<H>\d?\d):(?P<M>\d\d))?(:(?P<S>\d\d))?)? # hh:mm:ss
102+
(?P<o>.+)? # offset
103+
''', re.VERBOSE), serialised_re=re.compile(r'''
104+
(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)
105+
''', re.VERBOSE)):
106+
''' set the date to the value in spec
107+
'''
108+
m = serialised_re.match(spec)
109+
if m is not None:
110+
# we're serialised - easy!
111+
self.year, self.month, self.day, self.hour, self.minute, \
112+
self.second = map(int, m.groups()[:6])
113+
return
114+
115+
# not serialised data, try usual format
116+
m = date_re.match(spec)
117+
if m is None:
118+
raise ValueError, _('Not a date spec: [[yyyy-]mm-dd].'
119+
'[[h]h:mm[:ss]][offset]')
120+
121+
info = m.groupdict()
122+
123+
# get the current date as our default
124+
y,m,d,H,M,S,x,x,x = time.gmtime(time.time())
125+
126+
# override year, month, day parts
127+
if info['m'] is not None and info['d'] is not None:
128+
m = int(info['m'])
129+
d = int(info['d'])
130+
if info['y'] is not None:
131+
y = int(info['y'])
132+
# time defaults to 00:00:00 GMT - offset (local midnight)
133+
H = -offset
134+
M = S = 0
135+
136+
# override hour, minute, second parts
137+
if info['H'] is not None and info['M'] is not None:
138+
H = int(info['H']) - offset
139+
M = int(info['M'])
140+
S = 0
141+
if info['S'] is not None: S = int(info['S'])
142+
143+
# now handle the adjustment of hour
144+
ts = calendar.timegm((y,m,d,H,M,S,0,0,0))
145+
self.year, self.month, self.day, self.hour, self.minute, \
146+
self.second, x, x, x = time.gmtime(ts)
147+
148+
if info.get('o', None):
149+
try:
150+
self.applyInterval(Interval(info['o']))
151+
except ValueError:
152+
raise ValueError, _('Not a date spec: [[yyyy-]mm-dd].'
153+
'[[h]h:mm[:ss]][offset]')
154+
98155
def addInterval(self, interval):
99156
''' Add the interval to this date, returning the date tuple
100157
'''
@@ -219,59 +276,6 @@ def pretty(self, format='%d %B %Y'):
219276
return ' ' + str[1:]
220277
return str
221278

222-
def set(self, spec, offset=0, date_re=re.compile(r'''
223-
(((?P<y>\d\d\d\d)-)?((?P<m>\d\d?)-(?P<d>\d\d?))?)? # yyyy-mm-dd
224-
(?P<n>\.)? # .
225-
(((?P<H>\d?\d):(?P<M>\d\d))?(:(?P<S>\d\d))?)? # hh:mm:ss
226-
(?P<o>.+)? # offset
227-
''', re.VERBOSE), serialised_re=re.compile(r'''
228-
(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)
229-
''', re.VERBOSE)):
230-
''' set the date to the value in spec
231-
'''
232-
m = serialised_re.match(spec)
233-
if m is not None:
234-
# we're serialised - easy!
235-
self.year, self.month, self.day, self.hour, self.minute, \
236-
self.second = map(int, m.groups()[:6])
237-
return
238-
239-
# not serialised data, try usual format
240-
m = date_re.match(spec)
241-
if m is None:
242-
raise ValueError, _('Not a date spec: [[yyyy-]mm-dd].'
243-
'[[h]h:mm[:ss]][offset]')
244-
245-
info = m.groupdict()
246-
247-
# get the current date as our default
248-
y,m,d,H,M,S,x,x,x = time.gmtime(time.time())
249-
250-
# override year, month, day parts
251-
if info['m'] is not None and info['d'] is not None:
252-
m = int(info['m'])
253-
d = int(info['d'])
254-
if info['y'] is not None:
255-
y = int(info['y'])
256-
# time defaults to 00:00:00 GMT - offset (local midnight)
257-
H = -offset
258-
M = S = 0
259-
260-
# override hour, minute, second parts
261-
if info['H'] is not None and info['M'] is not None:
262-
H = int(info['H']) - offset
263-
M = int(info['M'])
264-
S = 0
265-
if info['S'] is not None: S = int(info['S'])
266-
267-
# now handle the adjustment of hour
268-
ts = calendar.timegm((y,m,d,H,M,S,0,0,0))
269-
self.year, self.month, self.day, self.hour, self.minute, \
270-
self.second, x, x, x = time.gmtime(ts)
271-
272-
if info.get('o', None):
273-
self.applyInterval(Interval(info['o']))
274-
275279
def __repr__(self):
276280
return '<Date %s>'%self.__str__()
277281

@@ -351,6 +355,46 @@ def __init__(self, spec, sign=1):
351355
self.year, self.month, self.day, self.hour, self.minute, \
352356
self.second = spec
353357

358+
def set(self, spec, interval_re=re.compile('''
359+
\s*(?P<s>[-+])? # + or -
360+
\s*((?P<y>\d+\s*)y)? # year
361+
\s*((?P<m>\d+\s*)m)? # month
362+
\s*((?P<w>\d+\s*)w)? # week
363+
\s*((?P<d>\d+\s*)d)? # day
364+
\s*(((?P<H>\d+):(?P<M>\d+))?(:(?P<S>\d+))?)? # time
365+
\s*''', re.VERBOSE), serialised_re=re.compile('''
366+
(?P<s>[+-])?1?(?P<y>([ ]{3}\d|\d{4}))(?P<m>\d{2})(?P<d>\d{2})
367+
(?P<H>\d{2})(?P<M>\d{2})(?P<S>\d{2})''', re.VERBOSE)):
368+
''' set the date to the value in spec
369+
'''
370+
self.year = self.month = self.week = self.day = self.hour = \
371+
self.minute = self.second = 0
372+
self.sign = 1
373+
m = serialised_re.match(spec)
374+
if not m:
375+
m = interval_re.match(spec)
376+
if not m:
377+
raise ValueError, _('Not an interval spec: [+-] [#y] [#m] [#w] '
378+
'[#d] [[[H]H:MM]:SS]')
379+
380+
info = m.groupdict()
381+
valid = 0
382+
for group, attr in {'y':'year', 'm':'month', 'w':'week', 'd':'day',
383+
'H':'hour', 'M':'minute', 'S':'second'}.items():
384+
if info.get(group, None) is not None:
385+
valid = 1
386+
setattr(self, attr, int(info[group]))
387+
388+
if not valid:
389+
raise ValueError, _('Not an interval spec: [+-] [#y] [#m] [#w] '
390+
'[#d] [[[H]H:MM]:SS]')
391+
392+
if self.week:
393+
self.day = self.day + self.week*7
394+
395+
if info['s'] is not None:
396+
self.sign = {'+':1, '-':-1}[info['s']]
397+
354398
def __cmp__(self, other):
355399
"""Compare this interval to another interval."""
356400
if other is None:
@@ -455,40 +499,6 @@ def __div__(self, other):
455499
d = seconds / 24
456500
return Interval((sign, 0, 0, d, H, M, S))
457501

458-
def set(self, spec, interval_re=re.compile('''
459-
\s*(?P<s>[-+])? # + or -
460-
\s*((?P<y>\d+\s*)y)? # year
461-
\s*((?P<m>\d+\s*)m)? # month
462-
\s*((?P<w>\d+\s*)w)? # week
463-
\s*((?P<d>\d+\s*)d)? # day
464-
\s*(((?P<H>\d+):(?P<M>\d+))?(:(?P<S>\d+))?)? # time
465-
\s*''', re.VERBOSE), serialised_re=re.compile('''
466-
(?P<s>[+-])?1?(?P<y>([ ]{3}\d|\d{4}))(?P<m>\d{2})(?P<d>\d{2})
467-
(?P<H>\d{2})(?P<M>\d{2})(?P<S>\d{2})''', re.VERBOSE)):
468-
''' set the date to the value in spec
469-
'''
470-
self.year = self.month = self.week = self.day = self.hour = \
471-
self.minute = self.second = 0
472-
self.sign = 1
473-
m = serialised_re.match(spec)
474-
if not m:
475-
m = interval_re.match(spec)
476-
if not m:
477-
raise ValueError, _('Not an interval spec: [+-] [#y] [#m] [#w] '
478-
'[#d] [[[H]H:MM]:SS]')
479-
480-
info = m.groupdict()
481-
for group, attr in {'y':'year', 'm':'month', 'w':'week', 'd':'day',
482-
'H':'hour', 'M':'minute', 'S':'second'}.items():
483-
if info.get(group, None) is not None:
484-
setattr(self, attr, int(info[group]))
485-
486-
if self.week:
487-
self.day = self.day + self.week*7
488-
489-
if info['s'] is not None:
490-
self.sign = {'+':1, '-':-1}[info['s']]
491-
492502
def __repr__(self):
493503
return '<Interval %s>'%self.__str__()
494504

test/test_dates.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
1616
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
1717
#
18-
# $Id: test_dates.py,v 1.20 2003-03-10 00:22:21 richard Exp $
18+
# $Id: test_dates.py,v 1.21 2003-03-19 03:25:30 richard Exp $
1919

2020
import unittest, time
2121

@@ -53,6 +53,9 @@ def testDate(self):
5353
date = Date("8:47:11")
5454
ae(str(date), '%s-%02d-%02d.08:47:11'%(y, m, d))
5555

56+
def testDateError(self):
57+
self.assertRaises(ValueError, Date, "12")
58+
5659
def testOffset(self):
5760
ae = self.assertEqual
5861
date = Date("2000-04-17", -5)

0 commit comments

Comments
 (0)