|  |  |  | @ -37,33 +37,101 @@ def shift_time(t, dt, localtime=True): | 
			
		
	
		
			
				
					|  |  |  |  |   else: | 
			
		
	
		
			
				
					|  |  |  |  |     return time.gmtime(t1) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def utime_to_iso(t=None, local=True): | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | class utime_to_iso_proc(object): | 
			
		
	
		
			
				
					|  |  |  |  |   """Converts UNIX time (seconds since Epoch) to ISO-formatted time string. | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   In order to ease time computation/conversion, | 
			
		
	
		
			
				
					|  |  |  |  |   we will use numeric TZ shift (+/-HH:MM) instead of | 
			
		
	
		
			
				
					|  |  |  |  |   letter TZ code (EDT, EST, GMT, etc). | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   The full ISO-8601 format is like this: | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     YYYY-MM-DDThh:mm:ss.fffffffff+AA:BB | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   where | 
			
		
	
		
			
				
					|  |  |  |  |   * YYYY-MM-DD = year, month, date | 
			
		
	
		
			
				
					|  |  |  |  |   * hh:mm:ss.fff = hour, minute, second, fraction of the second | 
			
		
	
		
			
				
					|  |  |  |  |   * AA:BB = time shift due to time zone | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   But some variants are valid: | 
			
		
	
		
			
				
					|  |  |  |  |   * YYYY-MM-DD hh:mm    (GNU ls timestyle 'long-iso') | 
			
		
	
		
			
				
					|  |  |  |  |   * YYYY-MM-DD hh:mm.ss.fffffffff +AA:BB    (GNU ls timestyle 'full-iso') | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   There are some built-in formats in this subroutine. | 
			
		
	
		
			
				
					|  |  |  |  |   They can be tweaked further (adding new formats is OK; but changing | 
			
		
	
		
			
				
					|  |  |  |  |   existing ones are not recommended). | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   The format string will undergo two passes: | 
			
		
	
		
			
				
					|  |  |  |  |   * first pass, via strftime | 
			
		
	
		
			
				
					|  |  |  |  |   * second pass, if '%' still exists in the string, expansion using 'opts' | 
			
		
	
		
			
				
					|  |  |  |  |     computed variables. | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   Identifiers for second pass must be named, and must use '%%(NAME)s' kind of | 
			
		
	
		
			
				
					|  |  |  |  |   format with double percent sign. | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   References: | 
			
		
	
		
			
				
					|  |  |  |  |   * http://www.cl.cam.ac.uk/~mgk25/iso-time.html | 
			
		
	
		
			
				
					|  |  |  |  |   * http://en.wikipedia.org/wiki/ISO_8601 | 
			
		
	
		
			
				
					|  |  |  |  |   * http://www.sqlite.org/lang_datefunc.html  (subheading "Time Strings") | 
			
		
	
		
			
				
					|  |  |  |  |   """ | 
			
		
	
		
			
				
					|  |  |  |  |   from time import time, localtime, gmtime, strftime, timezone | 
			
		
	
		
			
				
					|  |  |  |  |   if t == None: | 
			
		
	
		
			
				
					|  |  |  |  |     t = time() | 
			
		
	
		
			
				
					|  |  |  |  |   if local: | 
			
		
	
		
			
				
					|  |  |  |  |     tt = localtime(t) | 
			
		
	
		
			
				
					|  |  |  |  |     dtz = -timezone + tt.tm_isdst * 3600 | 
			
		
	
		
			
				
					|  |  |  |  |     # hopefully dtz is divisible by 60 | 
			
		
	
		
			
				
					|  |  |  |  |     # It would be silly for a gov't to make its time | 
			
		
	
		
			
				
					|  |  |  |  |     # differ by seconds to GMT! | 
			
		
	
		
			
				
					|  |  |  |  |     dsec = abs(dtz) % 60 | 
			
		
	
		
			
				
					|  |  |  |  |     dmin = abs(dtz // 60) % 60 | 
			
		
	
		
			
				
					|  |  |  |  |     dhr = dtz // 3600 | 
			
		
	
		
			
				
					|  |  |  |  |     if dsec == 00: | 
			
		
	
		
			
				
					|  |  |  |  |       sdtz = " %+03d:%02d" % (dhr, dmin) | 
			
		
	
		
			
				
					|  |  |  |  |   map_fmt_iso = { | 
			
		
	
		
			
				
					|  |  |  |  |     0: "%Y-%m-%d %H:%M:%S %%(TZ)s",  # original default of this routine | 
			
		
	
		
			
				
					|  |  |  |  |     'default': "%Y-%m-%d %H:%M:%S %%(TZ)s",  # original default of this routine | 
			
		
	
		
			
				
					|  |  |  |  |     # Global formats | 
			
		
	
		
			
				
					|  |  |  |  |     'iso8601': "%Y-%m-%dT%H:%M:%S.%%(NANOSECS)s%%(ZTZ)s", # formal ISO-8601 | 
			
		
	
		
			
				
					|  |  |  |  |     # GNU-specific formats | 
			
		
	
		
			
				
					|  |  |  |  |     'gnu long-iso': "%Y-%m-%d %H:%M", | 
			
		
	
		
			
				
					|  |  |  |  |     'gnu full-iso': "%Y-%m-%d %H:%M:%S.%%(NANOSECS)s %%(TZ)s", | 
			
		
	
		
			
				
					|  |  |  |  |     # My custom formats | 
			
		
	
		
			
				
					|  |  |  |  |     'idtstamp': "%Y-%m-%dT%H:%M:%S.%%(MILLISECS)s", | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  |   def __init__(self, fmt=0): | 
			
		
	
		
			
				
					|  |  |  |  |     from copy import copy | 
			
		
	
		
			
				
					|  |  |  |  |     # Make a copy so we don't clobber the original class: | 
			
		
	
		
			
				
					|  |  |  |  |     self.map_fmt_iso = copy(self.map_fmt_iso) | 
			
		
	
		
			
				
					|  |  |  |  |     self.fmt = fmt | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   def __call__(self, t=None, local=True, fmt=None): | 
			
		
	
		
			
				
					|  |  |  |  |     from time import time, localtime, gmtime, strftime, timezone | 
			
		
	
		
			
				
					|  |  |  |  |     if fmt == None: fmt = self.fmt | 
			
		
	
		
			
				
					|  |  |  |  |     if t == None: | 
			
		
	
		
			
				
					|  |  |  |  |       t = time() | 
			
		
	
		
			
				
					|  |  |  |  |     # The time, the nanosecond part: | 
			
		
	
		
			
				
					|  |  |  |  |     t_ns = int((t - int(t)) * 1e+9) | 
			
		
	
		
			
				
					|  |  |  |  |     opts = { | 
			
		
	
		
			
				
					|  |  |  |  |       'NANOSECS': ("%09.0f" % t_ns), | 
			
		
	
		
			
				
					|  |  |  |  |       'MICROSECS':  ("%06.0f" % (t_ns // 1000)), | 
			
		
	
		
			
				
					|  |  |  |  |       'MILLISECS':  ("%03.0f" % (t_ns // 1000000)), | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |     if local: | 
			
		
	
		
			
				
					|  |  |  |  |       tt = localtime(t) | 
			
		
	
		
			
				
					|  |  |  |  |       # dtz = Delta time due to Time Zone | 
			
		
	
		
			
				
					|  |  |  |  |       dtz = -timezone + tt.tm_isdst * 3600 | 
			
		
	
		
			
				
					|  |  |  |  |       # hopefully dtz is divisible by 60 | 
			
		
	
		
			
				
					|  |  |  |  |       # It would be silly for a gov't to make its time | 
			
		
	
		
			
				
					|  |  |  |  |       # differ by seconds to GMT! | 
			
		
	
		
			
				
					|  |  |  |  |       dsec = abs(dtz) % 60 | 
			
		
	
		
			
				
					|  |  |  |  |       dmin = abs(dtz // 60) % 60 | 
			
		
	
		
			
				
					|  |  |  |  |       dhr = dtz // 3600 | 
			
		
	
		
			
				
					|  |  |  |  |       if dsec == 00: | 
			
		
	
		
			
				
					|  |  |  |  |         opts['TZ'] = "%+03d:%02d" % (dhr, dmin) | 
			
		
	
		
			
				
					|  |  |  |  |       else: | 
			
		
	
		
			
				
					|  |  |  |  |         optz['TZ'] = "%+03d:%02d:%02d" % (dhr, dmin, dsec) | 
			
		
	
		
			
				
					|  |  |  |  |       opts['ZTZ'] = opts['TZ'] | 
			
		
	
		
			
				
					|  |  |  |  |     else: | 
			
		
	
		
			
				
					|  |  |  |  |       sdtz = " %+03d:%02d:%02d" % (dhr, dmin, dsec) | 
			
		
	
		
			
				
					|  |  |  |  |   else: | 
			
		
	
		
			
				
					|  |  |  |  |     tt = gmtime(t) | 
			
		
	
		
			
				
					|  |  |  |  |     sdtz = " +00:00" | 
			
		
	
		
			
				
					|  |  |  |  |   # Numeric timezone offset is created by hand | 
			
		
	
		
			
				
					|  |  |  |  |   # because I don't want to use %Z, nor do I want to use | 
			
		
	
		
			
				
					|  |  |  |  |   # "%z" (which did not work in python) | 
			
		
	
		
			
				
					|  |  |  |  |   return strftime("%Y-%m-%d %H:%M:%S", tt) + sdtz | 
			
		
	
		
			
				
					|  |  |  |  |       tt = gmtime(t) | 
			
		
	
		
			
				
					|  |  |  |  |       opts['TZ'] = "+00:00" | 
			
		
	
		
			
				
					|  |  |  |  |       opts['ZTZ'] = "Z" | 
			
		
	
		
			
				
					|  |  |  |  |     # Numeric timezone offset is created by hand | 
			
		
	
		
			
				
					|  |  |  |  |     # because I don't want to use %Z, nor do I want to use | 
			
		
	
		
			
				
					|  |  |  |  |     # "%z" (which did not work in python) | 
			
		
	
		
			
				
					|  |  |  |  |     fmt = self.map_fmt_iso.get(fmt, fmt) | 
			
		
	
		
			
				
					|  |  |  |  |     rslt1 = strftime(fmt, tt) | 
			
		
	
		
			
				
					|  |  |  |  |     if "%" in rslt1: | 
			
		
	
		
			
				
					|  |  |  |  |       rslt2 = rslt1 % opts | 
			
		
	
		
			
				
					|  |  |  |  |       return rslt2 | 
			
		
	
		
			
				
					|  |  |  |  |     else: | 
			
		
	
		
			
				
					|  |  |  |  |       return rslt1 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | utime_to_iso = utime_to_iso_proc() | 
			
		
	
	
		
			
				
					|  |  |  | 
 |