1"""Somewhat Looser ISO date format YYYY-MM-DD HH:mm:SS +HH:mm 2 3 ISO_date_loose -- YYYY-MM-DD format, with a month and day optional, 4 month or day may be specified without leading 0 5 ISO_time_loose -- HH:mm:SS format, with minutes and seconds optional 6 all numbers may be specified without leading 0 7 ISO_date_time_loose -- YYYY-MM-DD HH:mm:SS +HH:mm format, 8 with time optional and TimeZone offset optional, 9 same format for date and time as above 10 11Interpreter: 12 MxInterpreter 13 Interprets the parse tree as mx.DateTime values 14 Date and DateTime -> DateTime objects 15 Time only -> RelativeDateTime 16""" 17try: 18 from mx import DateTime 19 haveMX = 1 20except ImportError: 21 haveMX = 0 22from simpleparse.parser import Parser 23from simpleparse import common, objectgenerator 24from simpleparse.common import chartypes, numbers 25from simpleparse.dispatchprocessor import * 26 27c = {} 28declaration = """ 29<date_separator> := [-] 30<time_separator> := ':' 31offset_sign := [-+] 32 33year := int 34month := int 35day := int 36hour := int 37minute := int 38second := float/int 39ISO_date_loose := year, (date_separator, month, (date_separator, day)?)? 40ISO_time_loose := hour, (time_separator, minute, (time_separator, second)?)? 41offset := offset_sign, offset_hour, time_separator?, offset_minute? 42offset_hour := digit, digit 43offset_minute := digit, digit 44 45ISO_date_time_loose := ISO_date_loose, ([T ], ISO_time_loose)?, [ ]?, offset? 46""" 47 48_p = Parser( declaration ) 49for name in ["ISO_time_loose","ISO_date_time_loose", "ISO_date_loose"]: 50 c[ name ] = objectgenerator.LibraryElement( 51 generator = _p._generator, 52 production = name, 53 ) 54common.share( c ) 55 56if haveMX: 57 class MxInterpreter(DispatchProcessor): 58 """Interpret a parsed ISO_date_time_loose in GMT/UTC time or localtime 59 """ 60 int = numbers.IntInterpreter() 61 offset_minute = offset_hour = year = month = day = hour = minute = int 62 63 float = numbers.FloatInterpreter() 64 second = float 65 66 def __init__( 67 self, 68 inputLocal = 1, 69 returnLocal = 1, 70 ): 71 self.inputLocal = inputLocal 72 self.returnLocal = returnLocal 73 dateName = 'ISO_date_loose' 74 timeName = 'ISO_time_loose' 75 def ISO_date_time_loose( self, info, buffer): 76 """Interpret the loose ISO date + time format""" 77 (tag, left, right, sublist) = info 78 set = singleMap( sublist, self, buffer ) 79 base, time, offset = ( 80 set.get(self.dateName), 81 set.get(self.timeName) or DateTime.RelativeDateTime(hour=0,minute=0,second=0), 82 set.get( "offset" ), 83 ) 84 base = base + time 85 offset = set.get( "offset" ) 86 if offset is not None: 87 # an explicit timezone was entered, convert to gmt and return as appropriate... 88 gmt = base - offset 89 if self.returnLocal: 90 return gmt.localtime() 91 else: 92 return gmt 93 # was in the default input locale (either gmt or local) 94 if self.inputLocal and self.returnLocal: 95 return base 96 elif not self.inputLocal and not self.returnLocal: 97 return base 98 elif self.inputLocal and not self.returnLocal: 99 # return gmt from local... 100 return base.gmtime() 101 else: 102 return base.localtime() 103 def ISO_date_loose( self, info, buffer): 104 """Interpret the loose ISO date format""" 105 (tag, left, right, sublist) = info 106 set = singleMap( sublist, self, buffer ) 107 return DateTime.DateTime( 108 set.get("year") or now().year, 109 set.get("month") or 1, 110 set.get("day") or 1, 111 ) 112 def ISO_time_loose( self, info, buffer): 113 """Interpret the loose ISO time format""" 114 (tag, left, right, sublist) = info 115 set = singleMap( sublist, self, buffer ) 116 return DateTime.RelativeDateTime( 117 hour = set.get("hour") or 0, 118 minute = set.get("minute") or 0, 119 second = set.get("second") or 0, 120 ) 121 122 123 def offset( self, info, buffer): 124 """Calculate the time zone offset as a date-time delta""" 125 (tag, left, right, sublist) = info 126 set = singleMap( sublist, self, buffer ) 127 direction = set.get('offset_sign',1) 128 hour = set.get( "offset_hour", 0) 129 minute = set.get( "offset_minute", 0) 130 delta = DateTime.DateTimeDelta( 0, hour*direction, minute*direction) 131 return delta 132 133 def offset_sign( self , info, buffer): 134 """Interpret the offset sign as a multiplier""" 135 (tag, left, right, sublist) = info 136 v = buffer [left: right] 137 if v in ' +': 138 return 1 139 else: 140 return -1 141 142