from eon_helper import * class eon( object ): """ #+ # NAME: # class eon # PURPOSE: # Defines a class for storing times # PROCEDURE: # The main instance attributes are # # self.ticday integer, number of days since 2000/01/01 00:00:00 UT # i.e. Midnight, Jan 1, 2000 in the Gregorian calendar # self.tictac integer, represents the time of day in units of 1/10^self.exponent # self.exponent integer, defines the unit of self.tictac # # These three attributes must always be set by the __init__ method. # # Other time properties will be calculated only when needed, and are then # also stored as instance attributes for later recall. # This is sometimes already done by the __init__ method, but in general # this task is delegated to the __getattr__ method (which calculates and # stores the property when it is referenced as an attribute). # # Currently the following extra attributes are supported: # # jd # mjd # njd # posix # jepoch # bepoch # # Both Gregorian and Julian calendar are supported. This affects four # time properties: # # For Gregorian dates: # year # doy # month # day # # Julian dates are tracked separately: # julian_year # julian_doy # julian_month # julian_day # TODO: # Handle time zones. Currently everything is UTC. # - Input of times with timezone has been implemented (2012-05) # Probably should be handled similar to the Julian calendar. # # Documentation #- """ BadTypes = [type(None),type(NotImplemented)] def normalize(self): ''' #+ # NAME: # eon.normalize # PURPOSE: # (Internal purposes only) # Is used to normalize eon object (see PROCEDURE). # PROCEDURE: # Ensures that self.tictac is positive and is less than one # day. As a result self.ticday will always refer to the # midnight at the beginning of day (in UTC) for the eon object. # Note that neither self.ticday nor self.tictac are forced to # be integer. This is intentional. By the time this routine is # called (by eon.__init__) these quantities should already be # integers. # TODO??: make self-exponent as small as possible while keeping # tictac value exact. #- ''' tictacs_per_day = g_SECONDS_PER_DAY*10**self.exponent day, self.tictac = divmod(self.tictac,tictacs_per_day) self.ticday += day #tictac = self.tictac #i = 0 #n = tictac/10 #while i < self.exponent and tictac > 0 and n*10 == tictac: # tictac = n # n = tictac/10 # i += 1 #self.tictac = tictac #self.exponent -= i return def type(self): return 'eon_delta' if 'eon_delta' in str(self.__class__) else 'eon_date' def __repr__( self ): return '%s(ticday=%s,tictac=%s,exponent=%s)'%(self.type(), self.ticday, self.tictac, self.exponent) def __str__( self ): return '%s:%s:%s:%s'%(self.type(), self.ticday, self.tictac, self.exponent) def __eq__(self, tt): if type(tt) in eon.BadTypes: # This allows statement like tt == None return False # (Isn't it possible to define an eon NoneType??) exponent = max(self.exponent, tt.exponent) return self.ticday == tt.ticday and self.tictac*10**(exponent-self.exponent) == tt.tictac*10**(exponent-tt.exponent) def __ne__(self, tt): if type(tt) in eon.BadTypes: # This allows statement like tt != None return True exponent = max(self.exponent, tt.exponent) return self.ticday != tt.ticday or self.tictac*10**(exponent-self.exponent) != tt.tictac*10**(exponent-tt.exponent) def __lt__(self, tt): exponent = max(self.exponent, tt.exponent) return self.ticday < tt.ticday or (self.ticday == tt.ticday and self.tictac*10**(exponent-self.exponent) < tt.tictac*10**(exponent-tt.exponent)) def __le__(self, tt): exponent = max(self.exponent, tt.exponent) return self.ticday < tt.ticday or (self.ticday == tt.ticday and self.tictac*10**(exponent-self.exponent) <= tt.tictac*10**(exponent-tt.exponent)) def __gt__(self, tt): exponent = max(self.exponent, tt.exponent) return self.ticday > tt.ticday or (self.ticday == tt.ticday and self.tictac*10**(exponent-self.exponent) > tt.tictac*10**(exponent-tt.exponent)) def __ge__(self, tt): exponent = max(self.exponent, tt.exponent) return self.ticday > tt.ticday or (self.ticday == tt.ticday and self.tictac*10**(exponent-self.exponent) >= tt.tictac*10**(exponent-tt.exponent)) def __cmp__(self, tt): exponent = max(self.exponent, tt.exponent) self_tictac = self.tictac*10**(exponent-self.exponent) tt_tictac = tt.tictac *10**(exponent-tt.exponent ) return -1 if self.ticday < tt.ticday or (self.ticday == tt.ticday and self_tictac < tt_tictac) else \ 1 if self.ticday > tt.ticday or (self.ticday == tt.ticday and self_tictac > tt_tictac) else \ 0 def __coerce__(self, tt): return (self,tt) def __add__( self, tt ): if g_EON_DEBUG: print "method '%s:%s'"%(__name__,whoami()) return self.linear_transform(tt, factor=(1, 1), exponent=max(self.exponent,tt.exponent)) def __iadd__(self, tt): if g_EON_DEBUG: print "method '%s:%s'"%(__name__,whoami()) return NotImplemented def __radd__(self, tt): if g_EON_DEBUG: print "method '%s:%s'"%(__name__,whoami()) return NotImplemented def __sub__(self,tt): if g_EON_DEBUG: print "method '%s:%s'"%(__name__,whoami()) return self.linear_transform(tt, factor=(1,-1), exponent=max(self.exponent,tt.exponent)) def __isub__(self, tt): if g_EON_DEBUG: print "method '%s:%s'"%(__name__,whoami()) return NotImplemented def __rsub__(self, tt): if g_EON_DEBUG: print "method '%s:%s'"%(__name__,whoami()) return NotImplemented def __pos__(self): if g_EON_DEBUG: print "method '%s:%s'"%(__name__,whoami()) return self.linear_transform(factor= 1, exponent=self.exponent) def __neg__(self): if g_EON_DEBUG: print "method '%s:%s'"%(__name__,whoami()) return self.new(-self.ticday,-self.tictac) def __mul__(self, multiplier): if g_EON_DEBUG: print "method '%s:%s'"%(__name__,whoami()) return self.linear_transform(factor=multiplier) if isnumber(multiplier) else NotImplemented def __imul__(self, multiplier): if g_EON_DEBUG: print "method '%s:%s'"%(__name__,whoami()) return NotImplemented def __rmul__(self, multiplier): if g_EON_DEBUG: print "method '%s:%s'"%(__name__,whoami()) return self.__mul__(multiplier) def __div__(self, divider): if g_EON_DEBUG: print "method '%s:%s'"%(__name__,whoami()) if isinstance(divider,eon): u, f = divmod(self,divider) if f != f.zero(): tictacs_per_day = g_SECONDS_PER_DAY*10**f.exponent u += float(f.ticday*tictacs_per_day+f.tictac)/float(divider.ticday*tictacs_per_day+divider.tictac*10**(f.exponent-divider.exponent)) else: u = self.linear_transform(factor=1.0/divider) return u def __idiv__(self, divider): if g_EON_DEBUG: print "method '%s:%s'"%(__name__,whoami()) return NotImplemented def __rdiv__(self, divider): if g_EON_DEBUG: print "method '%s:%s'"%(__name__,whoami()) return NotImplemented def __abs__(self): if g_EON_DEBUG: print "method '%s:%s'"%(__name__,whoami()) return self.new(-self.ticday if self.ticday < 0 else self.ticday, -self.tictac if self.ticday < 0 else self.tictac) def __divmod__(self, tt): if g_EON_DEBUG: print "method '%s:%s'"%(__name__,whoami()) exponent = max(self.exponent,tt.exponent) tictacs_per_day = g_SECONDS_PER_DAY*10**exponent # Could cause integer overflow?? du = self.ticday*tictacs_per_day+self.tictac*10**(exponent-self.exponent) dt = tt.ticday *tictacs_per_day+tt.tictac *10**(exponent-tt.exponent ) nn, du = divmod(du,dt) nn = long(nn) ticday, tictac = fix_ds(0,0,0,0,du,exponent=exponent) u = self.new(ticday,tictac,exponent) u = (nn,u) return u def bot(self,dt): u = divmod(self,dt) return dt*u[0] def eot(self,dt): u = divmod(self,dt) return dt*(u[0]+1) def round(self,dt): ''' #+ # NAME: # eon_delta.round # PURPOSE: # Rounds to nearest multiple of a specified delta time # CALLING SEQUENCE: # dt_rounded = dt.round(du) # INPUTS: # du delta time object # OUTPUTS: # dt_rounded delta time object, rounded to nearest du #- ''' if g_EON_DEBUG: print "method '%s:%s'"%(__name__,whoami()) #u = self.__divmod__(dt) does the same u = divmod(self,dt) return dt*u[0] if u[1]/dt < 0.5 else dt*(u[0]+1) def linear_transform(self, tt=None, factor=None, exponent=None ): if g_EON_DEBUG: print "method '%s:%s'"%(__name__,whoami()) # Note that this does not compare the instance types, so it is the users # responsibility not to do anything silly, like adding a date to a date, etc. # When this is called from other methods, this check has been done. # factor = 1 : copy # factor = 1, exponent=exponent: smaller units of chipsec # factor = (0, 1): swap # factor = (1, 1): add # factor = (1,-1): subtract if exponent == None: exponent = self.exponent if tt == None: if factor == None: factor = 1 exponent = max(exponent, self.exponent) ticday = factor*self.ticday tictac = factor*self.tictac*10**(exponent-self.exponent) else: if factor == None: factor = (1,0) exponent = max(exponent, self.exponent, tt.exponent) ticday = factor[0]*self.ticday + factor[1]*tt.ticday tictac = factor[0]*self.tictac*10**(exponent-self.exponent) + factor[1]*tt.tictac*10**(exponent-tt.exponent) ticday, tictac = fix_ds(ticday,0,0,0,tictac,exponent=exponent) return self.new(ticday, tictac, exponent, tt) #+ # NAME: # eon.between # PURPOSE: # Check whether time is in specified time period # CALLING SEQUENCE: # is_between = tt.between( t0, t1) # PROCEDURE: # if both start_time and stop_time are not None then # True means start_time <= self < stop_time # if only start_time is not None then # True means self >= start_time. # If only stop_time is not None then # True mean self < stop_time # If both start_time and stop_time are None then # always True is returned #- def between(self, start_time, stop_time): #return False if (start_time != None and self < start_time) or (stop_time != None and self >= stop_time) else True status = True if start_time != None and self < start_time: status = False if stop_time != None and self >= stop_time: status = False return status def zero(self): return self.new(0,0) #def copy(self): # return self.new() def new( self, fnc, ticday=None, tictac=None, exponent=None ): if g_EON_DEBUG: print "method '%s:%s'"%(__name__,whoami()) u = fnc( ticday = self.ticday if ticday == None else ticday, tictac = self.tictac if tictac == None else tictac, exponent= self.exponent if exponent == None else exponent ) u.normalize() return u