1515# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
1616# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
1717#
18- # $Id: date.py,v 1.51 2003-03-22 22:43:21 richard Exp $
18+ # $Id: date.py,v 1.52 2003-04-21 14:29:39 kedder Exp $
1919
2020__doc__ = """
2121Date, time and time interval handling.
2424import time , re , calendar , types
2525from i18n import _
2626
27+ def _add_granularity (src , order , value = 1 ):
28+ '''Increment first non-None value in src dictionary ordered by 'order'
29+ parameter
30+ '''
31+ for gran in order :
32+ if src [gran ]:
33+ src [gran ] = int (src [gran ]) + value
34+ break
35+
2736class Date :
2837 '''
2938 As strings, date-and-time stamps are specified with the date in
@@ -80,15 +89,15 @@ class Date:
8089 minute, second) is the serialisation format returned by the serialise()
8190 method, and is accepted as an argument on instatiation.
8291 '''
83- def __init__ (self , spec = '.' , offset = 0 ):
92+ def __init__ (self , spec = '.' , offset = 0 , add_granularity = 0 ):
8493 """Construct a date given a specification and a time zone offset.
8594
8695 'spec' is a full date or a partial form, with an optional
8796 added or subtracted interval. Or a date 9-tuple.
8897 'offset' is the local time zone offset from GMT in hours.
8998 """
9099 if type (spec ) == type ('' ):
91- self .set (spec , offset = offset )
100+ self .set (spec , offset = offset , add_granularity = add_granularity )
92101 else :
93102 y ,m ,d ,H ,M ,S ,x ,x ,x = spec
94103 ts = calendar .timegm ((y ,m ,d ,H + offset ,M ,S ,0 ,0 ,0 ))
@@ -102,9 +111,10 @@ def set(self, spec, offset=0, date_re=re.compile(r'''
102111 (?P<o>.+)? # offset
103112 ''' , re .VERBOSE ), serialised_re = re .compile (r'''
104113 (\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)
105- ''' , re .VERBOSE )):
114+ ''' , re .VERBOSE ), add_granularity = 0 ):
106115 ''' set the date to the value in spec
107116 '''
117+
108118 m = serialised_re .match (spec )
109119 if m is not None :
110120 # we're serialised - easy!
@@ -120,6 +130,9 @@ def set(self, spec, offset=0, date_re=re.compile(r'''
120130
121131 info = m .groupdict ()
122132
133+ if add_granularity :
134+ _add_granularity (info , 'SMHdmy' )
135+
123136 # get the current date as our default
124137 y ,m ,d ,H ,M ,S ,x ,x ,x = time .gmtime (time .time ())
125138
@@ -140,6 +153,9 @@ def set(self, spec, offset=0, date_re=re.compile(r'''
140153 S = 0
141154 if info ['S' ] is not None : S = int (info ['S' ])
142155
156+ if add_granularity :
157+ S = S - 1
158+
143159 # now handle the adjustment of hour
144160 ts = calendar .timegm ((y ,m ,d ,H ,M ,S ,0 ,0 ,0 ))
145161 self .year , self .month , self .day , self .hour , self .minute , \
@@ -345,10 +361,10 @@ class Interval:
345361
346362 TODO: more examples, showing the order of addition operation
347363 '''
348- def __init__ (self , spec , sign = 1 , allowdate = 1 ):
364+ def __init__ (self , spec , sign = 1 , allowdate = 1 , add_granularity = 0 ):
349365 """Construct an interval given a specification."""
350366 if type (spec ) == type ('' ):
351- self .set (spec , allowdate )
367+ self .set (spec , allowdate = allowdate , add_granularity = add_granularity )
352368 else :
353369 if len (spec ) == 7 :
354370 self .sign , self .year , self .month , self .day , self .hour , \
@@ -372,7 +388,8 @@ def set(self, spec, allowdate=1, interval_re=re.compile('''
372388 (\d?\d:\d\d)?(:\d\d)? # hh:mm:ss
373389 )?''' , re .VERBOSE ), serialised_re = re .compile ('''
374390 (?P<s>[+-])?1?(?P<y>([ ]{3}\d|\d{4}))(?P<m>\d{2})(?P<d>\d{2})
375- (?P<H>\d{2})(?P<M>\d{2})(?P<S>\d{2})''' , re .VERBOSE )):
391+ (?P<H>\d{2})(?P<M>\d{2})(?P<S>\d{2})''' , re .VERBOSE ),
392+ add_granularity = 0 ):
376393 ''' set the date to the value in spec
377394 '''
378395 self .year = self .month = self .week = self .day = self .hour = \
@@ -389,6 +406,9 @@ def set(self, spec, allowdate=1, interval_re=re.compile('''
389406
390407 # pull out all the info specified
391408 info = m .groupdict ()
409+ if add_granularity :
410+ _add_granularity (info , 'SMHdwmy' , (info ['s' ]== '-' and - 1 or 1 ))
411+
392412 valid = 0
393413 for group , attr in {'y' :'year' , 'm' :'month' , 'w' :'week' , 'd' :'day' ,
394414 'H' :'hour' , 'M' :'minute' , 'S' :'second' }.items ():
@@ -654,7 +674,7 @@ class Range:
654674 <Range from None to 2003-03-09.20:00:00>
655675
656676 """
657- def __init__ (self , spec , Type , ** params ):
677+ def __init__ (self , spec , Type , allow_granularity = 1 , ** params ):
658678 """Initializes Range of type <Type> from given <spec> string.
659679
660680 Sets two properties - from_value and to_value. None assigned to any of
@@ -666,8 +686,8 @@ class instance.
666686
667687 """
668688 self .range_type = Type
669- re_range = r'(?:^|(?: from)? (.+?))(?:to(.+?)$|$)'
670- re_geek_range = r'(?:^|(.+?))(?:; (.+?)$|$)'
689+ re_range = r'(?:^|from(.+?))(?:to(.+?)$|$)'
690+ re_geek_range = r'(?:^|(.+?)); (?:(.+?)$|$)'
671691 # Check which syntax to use
672692 if spec .find (';' ) == - 1 :
673693 # Native english
@@ -682,7 +702,11 @@ class instance.
682702 if self .to_value :
683703 self .to_value = Type (self .to_value .strip (), ** params )
684704 else :
685- raise ValueError , "Invalid range"
705+ if allow_granularity :
706+ self .from_value = Type (spec , ** params )
707+ self .to_value = Type (spec , add_granularity = 1 , ** params )
708+ else :
709+ raise ValueError , "Invalid range"
686710
687711 def __str__ (self ):
688712 return "from %s to %s" % (self .from_value , self .to_value )
@@ -691,12 +715,17 @@ def __repr__(self):
691715 return "<Range %s>" % self .__str__ ()
692716
693717def test_range ():
694- rspecs = ("from 2-12 to 4-2" , "18:00 TO +2m" , "12:00" , "tO +3d" ,
695- "2002-11-10; 2002-12-12" , "; 20:00 +1d" )
718+ rspecs = ("from 2-12 to 4-2" , "from 18:00 TO +2m" , "12:00;" , "tO +3d" ,
719+ "2002-11-10; 2002-12-12" , "; 20:00 +1d" , '2002-10-12' )
720+ rispecs = ('from -1w 2d 4:32 to 4d' , '-2w 1d' )
696721 for rspec in rspecs :
697722 print '>>> Range("%s")' % rspec
698723 print `Range(rspec, Date)`
699724 print
725+ for rspec in rispecs :
726+ print '>>> Range("%s")' % rspec
727+ print `Range(rspec, Interval)`
728+ print
700729
701730def test ():
702731 intervals = (" 3w 1 d 2:00" , " + 2d" , "3w" )
@@ -705,7 +734,7 @@ def test():
705734 print `Interval(interval)`
706735
707736 dates = ("." , "2000-06-25.19:34:02" , ". + 2d" , "1997-04-17" , "01-25" ,
708- "08-13.22:13" , "14:25" )
737+ "08-13.22:13" , "14:25" , '2002-12' )
709738 for date in dates :
710739 print '>>> Date("%s")' % date
711740 print `Date(date)`
@@ -716,6 +745,6 @@ def test():
716745 print `Date(date) + Interval(interval)`
717746
718747if __name__ == '__main__' :
719- test_range ()
748+ test ()
720749
721750# vim: set filetype=python ts=4 sw=4 et si
0 commit comments