Mercurial > p > roundup > code
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 |
