| """Parse a timezone specification.""" |
| |
| # XXX Unfinished. |
| # XXX Only the typical form "XXXhhYYY;ddd/hh,ddd/hh" is currently supported. |
| |
| tzpat = ('^([A-Z][A-Z][A-Z])([-+]?[0-9]+)([A-Z][A-Z][A-Z]);' |
| '([0-9]+)/([0-9]+),([0-9]+)/([0-9]+)$') |
| |
| tzprog = None |
| |
| def tzparse(tzstr): |
| """Given a timezone spec, return a tuple of information |
| (tzname, delta, dstname, daystart, hourstart, dayend, hourend), |
| where 'tzname' is the name of the timezone, 'delta' is the offset |
| in hours from GMT, 'dstname' is the name of the daylight-saving |
| timezone, and 'daystart'/'hourstart' and 'dayend'/'hourend' |
| specify the starting and ending points for daylight saving time.""" |
| global tzprog |
| if tzprog == None: |
| import re |
| tzprog = re.compile(tzpat) |
| match = tzprog.match(tzstr) |
| if not match: |
| raise ValueError, 'not the TZ syntax I understand' |
| subs = [] |
| for i in range(1, 8): |
| subs.append(match.group(i)) |
| for i in (1, 3, 4, 5, 6): |
| subs[i] = eval(subs[i]) |
| [tzname, delta, dstname, daystart, hourstart, dayend, hourend] = subs |
| return (tzname, delta, dstname, daystart, hourstart, dayend, hourend) |
| |
| def tzlocaltime(secs, params): |
| """Given a Unix time in seconds and a tuple of information about |
| a timezone as returned by tzparse(), return the local time in the |
| form (year, month, day, hour, min, sec, yday, wday, tzname).""" |
| import time |
| (tzname, delta, dstname, daystart, hourstart, dayend, hourend) = params |
| year, month, days, hours, mins, secs, yday, wday, isdst = \ |
| time.gmtime(secs - delta*3600) |
| if (daystart, hourstart) <= (yday+1, hours) < (dayend, hourend): |
| tzname = dstname |
| hours = hours + 1 |
| return year, month, days, hours, mins, secs, yday, wday, tzname |
| |
| def tzset(): |
| """Determine the current timezone from the "TZ" environment variable.""" |
| global tzparams, timezone, altzone, daylight, tzname |
| import os |
| tzstr = os.environ['TZ'] |
| tzparams = tzparse(tzstr) |
| timezone = tzparams[1] * 3600 |
| altzone = timezone - 3600 |
| daylight = 1 |
| tzname = tzparams[0], tzparams[2] |
| |
| def isdst(secs): |
| """Return true if daylight-saving time is in effect for the given |
| Unix time in the current timezone.""" |
| import time |
| (tzname, delta, dstname, daystart, hourstart, dayend, hourend) = \ |
| tzparams |
| year, month, days, hours, mins, secs, yday, wday, isdst = \ |
| time.gmtime(secs - delta*3600) |
| return (daystart, hourstart) <= (yday+1, hours) < (dayend, hourend) |
| |
| tzset() |
| |
| def localtime(secs): |
| """Get the local time in the current timezone.""" |
| return tzlocaltime(secs, tzparams) |
| |
| def test(): |
| from time import asctime, gmtime |
| import time, sys |
| now = time.time() |
| x = localtime(now) |
| tm = x[:-1] + (0,) |
| print 'now =', now, '=', asctime(tm), x[-1] |
| now = now - now % (24*3600) |
| if sys.argv[1:]: now = now + eval(sys.argv[1]) |
| x = gmtime(now) |
| tm = x[:-1] + (0,) |
| print 'gmtime =', now, '=', asctime(tm), 'yday =', x[-2] |
| jan1 = now - x[-2]*24*3600 |
| x = localtime(jan1) |
| tm = x[:-1] + (0,) |
| print 'jan1 =', jan1, '=', asctime(tm), x[-1] |
| for d in range(85, 95) + range(265, 275): |
| t = jan1 + d*24*3600 |
| x = localtime(t) |
| tm = x[:-1] + (0,) |
| print 'd =', d, 't =', t, '=', asctime(tm), x[-1] |