• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

contrib/opal/ZSI/ZSI/TCtimes.py

00001 #! /usr/bin/env python
00002 # $Header$
00003 '''Typecodes for dates and times.
00004 '''
00005 
00006 from ZSI import _copyright, _floattypes, _inttypes, _get_idstr, EvaluateException
00007 from ZSI.TC import TypeCode, SimpleType
00008 from ZSI.wstools.Namespaces import SCHEMA
00009 import operator, re, time as _time
00010 from time import mktime as _mktime, localtime as _localtime, gmtime as _gmtime
00011 from datetime import tzinfo as _tzinfo, timedelta as _timedelta,\
00012     datetime as _datetime
00013 from math import modf as _modf
00014 
00015 _niltime = [
00016     0, 0, 0,    # year month day
00017     0, 0, 0,    # hour minute second
00018     0, 0, 0     # weekday, julian day, dst flag
00019 ]
00020 
00021 #### Code added to check current timezone offset
00022 _zero = _timedelta(0)
00023 _dstoffset = _stdoffset = _timedelta(seconds=-_time.timezone)
00024 if _time.daylight: _dstoffset = _timedelta(seconds=-_time.altzone)
00025 _dstdiff = _dstoffset - _stdoffset
00026 
00027 
00028 class _localtimezone(_tzinfo):
00029     """ """
00030     def dst(self, dt):
00031         """datetime -> DST offset in minutes east of UTC."""
00032         tt = _localtime(_mktime((dt.year, dt.month, dt.day,
00033                  dt.hour, dt.minute, dt.second, dt.weekday(), 0, -1)))
00034         if tt.tm_isdst > 0: return _dstdiff
00035         return _zero
00036     
00037     #def fromutc(...)
00038     #datetime in UTC -> datetime in local time.
00039 
00040     def tzname(self, dt):
00041         """datetime -> string name of time zone."""
00042         tt = _localtime(_mktime((dt.year, dt.month, dt.day,
00043                  dt.hour, dt.minute, dt.second, dt.weekday(), 0, -1)))
00044         return _time.tzname[tt.tm_isdst > 0]
00045 
00046     def utcoffset(self, dt):
00047         """datetime -> minutes east of UTC (negative for west of UTC)."""
00048         tt = _localtime(_mktime((dt.year, dt.month, dt.day,
00049                  dt.hour, dt.minute, dt.second, dt.weekday(), 0, -1)))
00050         if tt.tm_isdst > 0: return _dstoffset
00051         return _stdoffset
00052 
00053 class _fixedoffset(_tzinfo):
00054     """Fixed offset in minutes east from UTC.
00055     
00056     A class building tzinfo objects for fixed-offset time zones.
00057     Note that _fixedoffset(0, "UTC") is a different way to build a
00058     UTC tzinfo object.
00059     """
00060     #def __init__(self, offset, name):
00061     def __init__(self, offset):
00062         self.__offset = _timedelta(minutes=offset)
00063         #self.__name = name
00064         
00065     def dst(self, dt):
00066         """datetime -> DST offset in minutes east of UTC."""
00067         return _zero
00068     
00069     def tzname(self, dt):
00070         """datetime -> string name of time zone."""
00071         #return self.__name
00072         return "server"
00073     
00074     def utcoffset(self, dt):
00075         """datetime -> minutes east of UTC (negative for west of UTC)."""
00076         return self.__offset
00077 
00078     
00079 def _dict_to_tuple(d):
00080     '''Convert a dictionary to a time tuple.  Depends on key values in the
00081     regexp pattern!
00082     '''    
00083     # TODO: Adding a ms field to struct_time tuples is problematic 
00084     # since they don't have this field.  Should use datetime
00085     # which has a microseconds field, else no ms..  When mapping struct_time 
00086     # to gDateTime the last 3 fields are irrelevant, here using dummy values to make
00087     # everything happy.
00088     # 
00089 
00090     retval = _niltime[:]
00091     for k,i in ( ('Y', 0), ('M', 1), ('D', 2), ('h', 3), ('m', 4), ):
00092         v = d.get(k)
00093         if v: retval[i] = int(v)
00094         
00095     v = d.get('s')
00096     if v:
00097         msec,sec = _modf(float(v))
00098         retval[6],retval[5] = int(round(msec*1000)), int(sec)
00099             
00100     v = d.get('tz')
00101     if v and v != 'Z':
00102         h,m = map(int, v.split(':'))
00103         # check for time zone offset, if within the same timezone, 
00104         # ignore offset specific calculations
00105         offset=_localtimezone().utcoffset(_datetime.now())
00106         local_offset_hour = offset.seconds/3600
00107         local_offset_min = (offset.seconds%3600)%60
00108         if local_offset_hour > 12: 
00109             local_offset_hour -= 24
00110             
00111         if local_offset_hour != h or local_offset_min != m:                
00112             if h<0:
00113                 #TODO: why is this set to server
00114                 #foff = _fixedoffset(-((abs(h)*60+m)),"server")
00115                 foff = _fixedoffset(-((abs(h)*60+m)))
00116             else:
00117                 #TODO: why is this set to server
00118                 #foff = _fixedoffset((abs(h)*60+m),"server")
00119                 foff = _fixedoffset((abs(h)*60+m)) 
00120                 
00121             dt = _datetime(retval[0],retval[1],retval[2],retval[3],retval[4],
00122                            retval[5],0,foff)
00123             
00124             # update dict with calculated timezone
00125             localdt=dt.astimezone(_localtimezone())
00126             retval[0] = localdt.year
00127             retval[1] = localdt.month
00128             retval[2] = localdt.day
00129             retval[3] = localdt.hour
00130             retval[4] = localdt.minute
00131             retval[5] = localdt.second
00132             
00133     if d.get('neg', 0):
00134         retval[0:5] = map(operator.__neg__, retval[0:5])
00135     return tuple(retval)
00136 
00137 
00138 class Duration(SimpleType):
00139     '''Time duration.
00140     '''
00141     parselist = [ (None,'duration') ]
00142     lex_pattern = re.compile('^' r'(?P<neg>-?)P' \
00143                     r'((?P<Y>\d+)Y)?' r'((?P<M>\d+)M)?' r'((?P<D>\d+)D)?' \
00144                     r'(?P<T>T?)' r'((?P<h>\d+)H)?' r'((?P<m>\d+)M)?' \
00145                     r'((?P<s>\d*(\.\d+)?)S)?' '$')
00146     type = (SCHEMA.XSD3, 'duration')
00147 
00148 
00149     def text_to_data(self, text, elt, ps):
00150         '''convert text into typecode specific data.
00151         '''
00152         if text is None:
00153             return None
00154         m = Duration.lex_pattern.match(text)
00155         if m is None:
00156             raise EvaluateException('Illegal duration', ps.Backtrace(elt))
00157         d = m.groupdict()
00158         if d['T'] and (d['h'] is None and d['m'] is None and d['s'] is None):
00159             raise EvaluateException('Duration has T without time')
00160         try:
00161             retval = _dict_to_tuple(d)
00162         except ValueError, e:
00163             raise EvaluateException(str(e))
00164     
00165         if self.pyclass is not None:
00166             return self.pyclass(retval)
00167         return retval  
00168     
00169     def get_formatted_content(self, pyobj):
00170         if type(pyobj) in _floattypes or type(pyobj) in _inttypes:
00171             pyobj = _gmtime(pyobj)
00172         
00173         d = {}
00174         pyobj = tuple(pyobj)
00175         if 1 in map(lambda x: x < 0, pyobj[0:6]):
00176             pyobj = map(abs, pyobj)
00177             neg = '-'
00178         else:
00179             neg = ''
00180             
00181         val = '%sP%dY%dM%dDT%dH%dM%dS' % \
00182             ( neg, pyobj[0], pyobj[1], pyobj[2], pyobj[3], pyobj[4], pyobj[5])
00183 
00184         return val
00185         
00186 
00187 class Gregorian(SimpleType):
00188     '''Gregorian times.
00189     '''
00190     lex_pattern = tag = format = None
00191 
00192     def text_to_data(self, text, elt, ps):
00193         '''convert text into typecode specific data.
00194         '''
00195         if text is None:
00196             return None
00197         
00198         m = self.lex_pattern.match(text)
00199         if not m:
00200             raise EvaluateException('Bad Gregorian: %s' %text, ps.Backtrace(elt))
00201         try:
00202             retval = _dict_to_tuple(m.groupdict())
00203         except ValueError, e:
00204             #raise EvaluateException(str(e))
00205             raise
00206         
00207         if self.pyclass is not None:
00208             return self.pyclass(retval)
00209         return retval    
00210 
00211     def get_formatted_content(self, pyobj):
00212         if type(pyobj) in _floattypes or type(pyobj) in _inttypes:
00213             pyobj = _gmtime(pyobj)
00214         
00215         d = {}
00216         pyobj = tuple(pyobj)
00217         if 1 in map(lambda x: x < 0, pyobj[0:6]):
00218             pyobj = map(abs, pyobj)
00219             d['neg'] = '-'
00220         else:
00221             d['neg'] = ''
00222 
00223         ms = pyobj[6]
00224         if not ms or not hasattr(self, 'format_ms'): 
00225             d = { 'Y': pyobj[0], 'M': pyobj[1], 'D': pyobj[2],
00226                 'h': pyobj[3], 'm': pyobj[4], 's': pyobj[5], }
00227             return self.format % d
00228 
00229         if  ms > 999:
00230             raise ValueError, 'milliseconds must be a integer between 0 and 999'
00231 
00232         d = { 'Y': pyobj[0], 'M': pyobj[1], 'D': pyobj[2],
00233             'h': pyobj[3], 'm': pyobj[4], 's': pyobj[5], 'ms':ms, }
00234         return self.format_ms % d
00235  
00236 
00237 class gDateTime(Gregorian):
00238     '''A date and time.
00239     '''
00240     parselist = [ (None,'dateTime') ]
00241     lex_pattern = re.compile('^' r'(?P<neg>-?)' \
00242                         '(?P<Y>\d{4,})-' r'(?P<M>\d\d)-' r'(?P<D>\d\d)' 'T' \
00243                         r'(?P<h>\d\d):' r'(?P<m>\d\d):' r'(?P<s>\d*(\.\d+)?)' \
00244                         r'(?P<tz>(Z|([-+]\d\d:\d\d))?)' '$')
00245     tag, format = 'dateTime', '%(Y)04d-%(M)02d-%(D)02dT%(h)02d:%(m)02d:%(s)02dZ'
00246     format_ms = format[:-1] + '.%(ms)03dZ'
00247     type = (SCHEMA.XSD3, 'dateTime')
00248 
00249 class gDate(Gregorian):
00250     '''A date.
00251     '''
00252     parselist = [ (None,'date') ]
00253     lex_pattern = re.compile('^' r'(?P<neg>-?)' \
00254                         '(?P<Y>\d{4,})-' r'(?P<M>\d\d)-' r'(?P<D>\d\d)' \
00255                         r'(?P<tz>Z|([-+]\d\d:\d\d))?' '$')
00256     tag, format = 'date', '%(Y)04d-%(M)02d-%(D)02dZ'
00257     type = (SCHEMA.XSD3, 'date')
00258 
00259 class gYearMonth(Gregorian):
00260     '''A date.
00261     '''
00262     parselist = [ (None,'gYearMonth') ]
00263     lex_pattern = re.compile('^' r'(?P<neg>-?)' \
00264                         '(?P<Y>\d{4,})-' r'(?P<M>\d\d)' \
00265                         r'(?P<tz>Z|([-+]\d\d:\d\d))?' '$')
00266     tag, format = 'gYearMonth', '%(Y)04d-%(M)02dZ'
00267     type = (SCHEMA.XSD3, 'gYearMonth')
00268 
00269 class gYear(Gregorian):
00270     '''A date.
00271     '''
00272     parselist = [ (None,'gYear') ]
00273     lex_pattern = re.compile('^' r'(?P<neg>-?)' \
00274                         '(?P<Y>\d{4,})' \
00275                         r'(?P<tz>Z|([-+]\d\d:\d\d))?' '$')
00276     tag, format = 'gYear', '%(Y)04dZ'
00277     type = (SCHEMA.XSD3, 'gYear')
00278 
00279 class gMonthDay(Gregorian):
00280     '''A gMonthDay.
00281     '''
00282     parselist = [ (None,'gMonthDay') ]
00283     lex_pattern = re.compile('^' r'(?P<neg>-?)' \
00284                         r'--(?P<M>\d\d)-' r'(?P<D>\d\d)' \
00285                         r'(?P<tz>Z|([-+]\d\d:\d\d))?' '$')
00286     tag, format = 'gMonthDay', '---%(M)02d-%(D)02dZ'
00287     type = (SCHEMA.XSD3, 'gMonthDay')
00288 
00289 
00290 class gDay(Gregorian):
00291     '''A gDay.
00292     '''
00293     parselist = [ (None,'gDay') ]
00294     lex_pattern = re.compile('^' r'(?P<neg>-?)' \
00295                         r'---(?P<D>\d\d)' \
00296                         r'(?P<tz>Z|([-+]\d\d:\d\d))?' '$')
00297     tag, format = 'gDay', '---%(D)02dZ'
00298     type = (SCHEMA.XSD3, 'gDay')
00299     
00300 class gMonth(Gregorian):
00301     '''A gMonth.
00302     '''
00303     parselist = [ (None,'gMonth') ]
00304     lex_pattern = re.compile('^' r'(?P<neg>-?)' \
00305                         r'---(?P<M>\d\d)' \
00306                         r'(?P<tz>Z|([-+]\d\d:\d\d))?' '$')
00307     tag, format = 'gMonth', '---%(M)02dZ'
00308     type = (SCHEMA.XSD3, 'gMonth')
00309     
00310 class gTime(Gregorian):
00311     '''A time.
00312     '''
00313     parselist = [ (None,'time') ]
00314     lex_pattern = re.compile('^' r'(?P<neg>-?)' \
00315                         r'(?P<h>\d\d):' r'(?P<m>\d\d):' r'(?P<s>\d*(\.\d+)?)' \
00316                         r'(?P<tz>Z|([-+]\d\d:\d\d))?' '$')
00317     tag, format = 'time', '%(h)02d:%(m)02d:%(s)02dZ'
00318     format_ms = format[:-1] + '.%(ms)03dZ'
00319     type = (SCHEMA.XSD3, 'time')
00320 
00321 if __name__ == '__main__': print _copyright

Generated on Wed Oct 20 2010 11:12:16 for APBS by  doxygen 1.7.2