comparison roundup/date.py @ 1537:0e36c9b23aa6

more lenient date input and addition Interval input support [SF#677764]
author Richard Jones <richard@users.sourceforge.net>
date Wed, 19 Mar 2003 05:18:11 +0000
parents 26f29449c494
children 3faabaeab6aa
comparison
equal deleted inserted replaced
1536:3408d091da5b 1537:0e36c9b23aa6
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.49 2003-03-19 03:25:30 richard Exp $ 18 # $Id: date.py,v 1.50 2003-03-19 05:18:10 richard Exp $
19 19
20 __doc__ = """ 20 __doc__ = """
21 Date, time and time interval handling. 21 Date, time and time interval handling.
22 """ 22 """
23 23
94 ts = calendar.timegm((y,m,d,H+offset,M,S,0,0,0)) 94 ts = calendar.timegm((y,m,d,H+offset,M,S,0,0,0))
95 self.year, self.month, self.day, self.hour, self.minute, \ 95 self.year, self.month, self.day, self.hour, self.minute, \
96 self.second, x, x, x = time.gmtime(ts) 96 self.second, x, x, x = time.gmtime(ts)
97 97
98 def set(self, spec, offset=0, date_re=re.compile(r''' 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 99 (((?P<y>\d\d\d\d)[/-])?(?P<m>\d\d?)?[/-](?P<d>\d\d?))? # [yyyy-]mm-dd
100 (?P<n>\.)? # . 100 (?P<n>\.)? # .
101 (((?P<H>\d?\d):(?P<M>\d\d))?(:(?P<S>\d\d))?)? # hh:mm:ss 101 (((?P<H>\d?\d):(?P<M>\d\d))?(:(?P<S>\d\d))?)? # hh:mm:ss
102 (?P<o>.+)? # offset 102 (?P<o>.+)? # offset
103 ''', re.VERBOSE), serialised_re=re.compile(r''' 103 ''', re.VERBOSE), serialised_re=re.compile(r'''
104 (\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d) 104 (\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)
145 self.year, self.month, self.day, self.hour, self.minute, \ 145 self.year, self.month, self.day, self.hour, self.minute, \
146 self.second, x, x, x = time.gmtime(ts) 146 self.second, x, x, x = time.gmtime(ts)
147 147
148 if info.get('o', None): 148 if info.get('o', None):
149 try: 149 try:
150 self.applyInterval(Interval(info['o'])) 150 self.applyInterval(Interval(info['o'], allowdate=0))
151 except ValueError: 151 except ValueError:
152 raise ValueError, _('Not a date spec: [[yyyy-]mm-dd].' 152 raise ValueError, _('Not a date spec: [[yyyy-]mm-dd].'
153 '[[h]h:mm[:ss]][offset]') 153 '[[h]h:mm[:ss]][offset]')
154 154
155 def addInterval(self, interval): 155 def addInterval(self, interval):
319 <Interval + 1:59:59> 319 <Interval + 1:59:59>
320 >>> Interval('1y')/2 320 >>> Interval('1y')/2
321 <Interval + 6m> 321 <Interval + 6m>
322 >>> Interval('1:00')/2 322 >>> Interval('1:00')/2
323 <Interval + 0:30> 323 <Interval + 0:30>
324 >>> Interval('2003-03-18')
325 <Interval + [number of days between now and 2003-03-18]>
326 >>> Interval('-4d 2003-03-18')
327 <Interval + [number of days between now and 2003-03-14]>
324 328
325 Interval arithmetic is handled in a couple of special ways, trying 329 Interval arithmetic is handled in a couple of special ways, trying
326 to cater for the most common cases. Fundamentally, Intervals which 330 to cater for the most common cases. Fundamentally, Intervals which
327 have both date and time parts will result in strange results in 331 have both date and time parts will result in strange results in
328 arithmetic - because of the impossibility of handling day->month->year 332 arithmetic - because of the impossibility of handling day->month->year
339 minute, second) is the serialisation format returned by the serialise() 343 minute, second) is the serialisation format returned by the serialise()
340 method, and is accepted as an argument on instatiation. 344 method, and is accepted as an argument on instatiation.
341 345
342 TODO: more examples, showing the order of addition operation 346 TODO: more examples, showing the order of addition operation
343 ''' 347 '''
344 def __init__(self, spec, sign=1): 348 def __init__(self, spec, sign=1, allowdate=1):
345 """Construct an interval given a specification.""" 349 """Construct an interval given a specification."""
346 if type(spec) == type(''): 350 if type(spec) == type(''):
347 self.set(spec) 351 self.set(spec, allowdate)
348 else: 352 else:
349 if len(spec) == 7: 353 if len(spec) == 7:
350 self.sign, self.year, self.month, self.day, self.hour, \ 354 self.sign, self.year, self.month, self.day, self.hour, \
351 self.minute, self.second = spec 355 self.minute, self.second = spec
352 else: 356 else:
353 # old, buggy spec form 357 # old, buggy spec form
354 self.sign = sign 358 self.sign = sign
355 self.year, self.month, self.day, self.hour, self.minute, \ 359 self.year, self.month, self.day, self.hour, self.minute, \
356 self.second = spec 360 self.second = spec
357 361
358 def set(self, spec, interval_re=re.compile(''' 362 def set(self, spec, allowdate=1, interval_re=re.compile('''
359 \s*(?P<s>[-+])? # + or - 363 \s*(?P<s>[-+])? # + or -
360 \s*((?P<y>\d+\s*)y)? # year 364 \s*((?P<y>\d+\s*)y)? # year
361 \s*((?P<m>\d+\s*)m)? # month 365 \s*((?P<m>\d+\s*)m)? # month
362 \s*((?P<w>\d+\s*)w)? # week 366 \s*((?P<w>\d+\s*)w)? # week
363 \s*((?P<d>\d+\s*)d)? # day 367 \s*((?P<d>\d+\s*)d)? # day
364 \s*(((?P<H>\d+):(?P<M>\d+))?(:(?P<S>\d+))?)? # time 368 \s*(((?P<H>\d+):(?P<M>\d+))?(:(?P<S>\d+))?)? # time
365 \s*''', re.VERBOSE), serialised_re=re.compile(''' 369 \s*(?P<D>
370 (\d\d\d\d[/-])?(\d\d?)?[/-](\d\d?)? # [yyyy-]mm-dd
371 \.? # .
372 (\d?\d:\d\d)?(:\d\d)? # hh:mm:ss
373 )?''', re.VERBOSE), serialised_re=re.compile('''
366 (?P<s>[+-])?1?(?P<y>([ ]{3}\d|\d{4}))(?P<m>\d{2})(?P<d>\d{2}) 374 (?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)): 375 (?P<H>\d{2})(?P<M>\d{2})(?P<S>\d{2})''', re.VERBOSE)):
368 ''' set the date to the value in spec 376 ''' set the date to the value in spec
369 ''' 377 '''
370 self.year = self.month = self.week = self.day = self.hour = \ 378 self.year = self.month = self.week = self.day = self.hour = \
373 m = serialised_re.match(spec) 381 m = serialised_re.match(spec)
374 if not m: 382 if not m:
375 m = interval_re.match(spec) 383 m = interval_re.match(spec)
376 if not m: 384 if not m:
377 raise ValueError, _('Not an interval spec: [+-] [#y] [#m] [#w] ' 385 raise ValueError, _('Not an interval spec: [+-] [#y] [#m] [#w] '
378 '[#d] [[[H]H:MM]:SS]') 386 '[#d] [[[H]H:MM]:SS] [date spec]')
379 387
388 # pull out all the info specified
380 info = m.groupdict() 389 info = m.groupdict()
381 valid = 0 390 valid = 0
382 for group, attr in {'y':'year', 'm':'month', 'w':'week', 'd':'day', 391 for group, attr in {'y':'year', 'm':'month', 'w':'week', 'd':'day',
383 'H':'hour', 'M':'minute', 'S':'second'}.items(): 392 'H':'hour', 'M':'minute', 'S':'second'}.items():
384 if info.get(group, None) is not None: 393 if info.get(group, None) is not None:
385 valid = 1 394 valid = 1
386 setattr(self, attr, int(info[group])) 395 setattr(self, attr, int(info[group]))
387 396
388 if not valid: 397 # make sure it's valid
398 if not valid and not info['D']:
389 raise ValueError, _('Not an interval spec: [+-] [#y] [#m] [#w] ' 399 raise ValueError, _('Not an interval spec: [+-] [#y] [#m] [#w] '
390 '[#d] [[[H]H:MM]:SS]') 400 '[#d] [[[H]H:MM]:SS]')
391 401
392 if self.week: 402 if self.week:
393 self.day = self.day + self.week*7 403 self.day = self.day + self.week*7
394 404
395 if info['s'] is not None: 405 if info['s'] is not None:
396 self.sign = {'+':1, '-':-1}[info['s']] 406 self.sign = {'+':1, '-':-1}[info['s']]
407
408 # use a date spec if one is given
409 if allowdate and info['D'] is not None:
410 now = Date('.')
411 date = Date(info['D'])
412 # if no time part was specified, nuke it in the "now" date
413 if not date.hour or date.minute or date.second:
414 now.hour = now.minute = now.second = 0
415 if date != now:
416 y = now - (date + self)
417 self.__init__(y.get_tuple())
397 418
398 def __cmp__(self, other): 419 def __cmp__(self, other):
399 """Compare this interval to another interval.""" 420 """Compare this interval to another interval."""
400 if other is None: 421 if other is None:
401 # we are always larger than None 422 # we are always larger than None

Roundup Issue Tracker: http://roundup-tracker.org/