comparison roundup/date.py @ 3822:2a60b68985db

Fix arbitrary limit on dates. Dates can now be in the year-range 1-9999 for all backends except metakit which is still limited to 1970-2038.
author Ralf Schlatterbeck <schlatterbeck@users.sourceforge.net>
date Fri, 09 Mar 2007 10:25:10 +0000
parents 842f1a292ff8
children 7cda5b4daa91
comparison
equal deleted inserted replaced
3821:5ed4c9d30148 3822:2a60b68985db
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.89 2006-12-28 22:38:02 richard Exp $ 18 # $Id: date.py,v 1.90 2007-03-09 10:25:09 schlatterbeck Exp $
19 19
20 """Date, time and time interval handling. 20 """Date, time and time interval handling.
21 """ 21 """
22 __docformat__ = 'restructuredtext' 22 __docformat__ = 'restructuredtext'
23 23
261 self.set(spec, offset=offset, add_granularity=add_granularity) 261 self.set(spec, offset=offset, add_granularity=add_granularity)
262 return 262 return
263 elif isinstance(spec, datetime.datetime): 263 elif isinstance(spec, datetime.datetime):
264 # Python 2.3+ datetime object 264 # Python 2.3+ datetime object
265 y,m,d,H,M,S,x,x,x = spec.timetuple() 265 y,m,d,H,M,S,x,x,x = spec.timetuple()
266 if y < 1970: raise ValueError, 'year must be > 1970'
267 S += spec.microsecond/1000000. 266 S += spec.microsecond/1000000.
268 spec = (y,m,d,H,M,S,x,x,x) 267 spec = (y,m,d,H,M,S,x,x,x)
269 elif hasattr(spec, 'tuple'): 268 elif hasattr(spec, 'tuple'):
270 spec = spec.tuple() 269 spec = spec.tuple()
271 elif isinstance(spec, Date): 270 elif isinstance(spec, Date):
272 spec = spec.get_tuple() 271 spec = spec.get_tuple()
273 try: 272 try:
274 y,m,d,H,M,S,x,x,x = spec 273 y,m,d,H,M,S,x,x,x = spec
275 if y < 1970: raise ValueError, 'year must be > 1970'
276 frac = S - int(S) 274 frac = S - int(S)
277 self.year, self.month, self.day, self.hour, self.minute, \ 275 self.year, self.month, self.day, self.hour, self.minute, \
278 self.second = _local_to_utc(y, m, d, H, M, S, offset) 276 self.second = _local_to_utc(y, m, d, H, M, S, offset)
279 # we lost the fractional part 277 # we lost the fractional part
280 self.second = self.second + frac 278 self.second = self.second + frac
307 305
308 if add_granularity: 306 if add_granularity:
309 _add_granularity(info, 'SMHdmyab') 307 _add_granularity(info, 'SMHdmyab')
310 308
311 # get the current date as our default 309 # get the current date as our default
312 ts = time.time() 310 dt = datetime.datetime.utcnow()
313 frac = ts - int(ts) 311 y,m,d,H,M,S,x,x,x = dt.timetuple()
314 y,m,d,H,M,S,x,x,x = time.gmtime(ts) 312 S += dt.microsecond/1000000.
315 # gmtime loses the fractional seconds
316 S = S + frac
317 if str(S) == '60.0': S = 59.9
318 313
319 # whether we need to convert to UTC 314 # whether we need to convert to UTC
320 adjust = False 315 adjust = False
321 316
322 if info['y'] is not None or info['a'] is not None: 317 if info['y'] is not None or info['a'] is not None:
323 if info['y'] is not None: 318 if info['y'] is not None:
324 y = int(info['y']) 319 y = int(info['y'])
325 if y < 1970: raise ValueError, 'year must be > 1970'
326 m,d = (1,1) 320 m,d = (1,1)
327 if info['m'] is not None: 321 if info['m'] is not None:
328 m = int(info['m']) 322 m = int(info['m'])
329 if info['d'] is not None: 323 if info['d'] is not None:
330 d = int(info['d']) 324 d = int(info['d'])
342 S = 0 336 S = 0
343 if info['S'] is not None: 337 if info['S'] is not None:
344 S = float(info['S']) 338 S = float(info['S'])
345 adjust = True 339 adjust = True
346 340
347 if add_granularity:
348 S = S - 1
349 341
350 # now handle the adjustment of hour 342 # now handle the adjustment of hour
351 frac = S - int(S) 343 frac = S - int(S)
352 ts = calendar.timegm((y,m,d,H,M,S,0,0,0)) 344 dt = datetime.datetime(y,m,d,H,M,int(S), int(frac * 1000000.))
353 y, m, d, H, M, S, x, x, x = time.gmtime(ts) 345 if add_granularity:
346 dt = dt - datetime.timedelta(seconds=1)
347 y, m, d, H, M, S, x, x, x = dt.timetuple()
354 if adjust: 348 if adjust:
355 y, m, d, H, M, S = _local_to_utc(y, m, d, H, M, S, offset) 349 y, m, d, H, M, S = _local_to_utc(y, m, d, H, M, S, offset)
356 self.year, self.month, self.day, self.hour, self.minute, \ 350 self.year, self.month, self.day, self.hour, self.minute, \
357 self.second = y, m, d, H, M, S 351 self.second = y, m, d, H, M, S
358 # we lost the fractional part along the way 352 # we lost the fractional part along the way
359 self.second = self.second + frac 353 self.second += dt.microsecond/1000000.
360 if str(self.second) == '60.0': self.second = 59.9
361 354
362 if info.get('o', None): 355 if info.get('o', None):
363 try: 356 try:
364 self.applyInterval(Interval(info['o'], allowdate=0)) 357 self.applyInterval(Interval(info['o'], allowdate=0))
365 except ValueError: 358 except ValueError:
491 def __str__(self): 484 def __str__(self):
492 """Return this date as a string in the yyyy-mm-dd.hh:mm:ss format.""" 485 """Return this date as a string in the yyyy-mm-dd.hh:mm:ss format."""
493 return self.formal() 486 return self.formal()
494 487
495 def formal(self, sep='.', sec='%02d'): 488 def formal(self, sep='.', sec='%02d'):
496 f = '%%4d-%%02d-%%02d%s%%02d:%%02d:%s'%(sep, sec) 489 f = '%%04d-%%02d-%%02d%s%%02d:%%02d:%s'%(sep, sec)
497 return f%(self.year, self.month, self.day, self.hour, self.minute, 490 return f%(self.year, self.month, self.day, self.hour, self.minute,
498 self.second) 491 self.second)
499 492
500 def pretty(self, format='%d %B %Y'): 493 def pretty(self, format='%d %B %Y'):
501 ''' print up the date date using a pretty format... 494 ''' print up the date date using a pretty format...
502 495
503 Note that if the day is zero, and the day appears first in the 496 Note that if the day is zero, and the day appears first in the
504 format, then the day number will be removed from output. 497 format, then the day number will be removed from output.
505 ''' 498 '''
506 # Python2.4 strftime() enforces the non-zero-ness of the day-of-year 499 dt = datetime.datetime(self.year, self.month, self.day, self.hour,
507 # component of the time tuple, so we need to figure it out 500 self.minute, int(self.second),
508 t = (self.year, self.month, self.day, self.hour, self.minute, 501 (self.second - int (self.second)) * 1000000.)
509 int(self.second), 0, 0, 0) 502 str = dt.strftime(format)
510 t = calendar.timegm(t)
511 t = time.gmtime(t)
512 str = time.strftime(format, t)
513 503
514 # handle zero day by removing it 504 # handle zero day by removing it
515 if format.startswith('%d') and str[0] == '0': 505 if format.startswith('%d') and str[0] == '0':
516 return ' ' + str[1:] 506 return ' ' + str[1:]
517 return str 507 return str
533 def get_tuple(self): 523 def get_tuple(self):
534 return (self.year, self.month, self.day, self.hour, self.minute, 524 return (self.year, self.month, self.day, self.hour, self.minute,
535 self.second, 0, 0, 0) 525 self.second, 0, 0, 0)
536 526
537 def serialise(self): 527 def serialise(self):
538 return '%4d%02d%02d%02d%02d%06.3f'%(self.year, self.month, 528 return '%04d%02d%02d%02d%02d%06.3f'%(self.year, self.month,
539 self.day, self.hour, self.minute, self.second) 529 self.day, self.hour, self.minute, self.second)
540 530
541 def timestamp(self): 531 def timestamp(self):
542 ''' return a UNIX timestamp for this date ''' 532 ''' return a UNIX timestamp for this date '''
543 frac = self.second - int(self.second) 533 frac = self.second - int(self.second)

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