|
|
|
@ -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() |
|
|
|
|