#!/usr/bin/env python3 # http://inamidst.com/saxo/ # Created by Sean B. Palmer import itertools import os import struct import sys import time def parse(name): # Specification from http://69.36.11.139/tzdb/tzfile-format.html # tzfile(5) also gives the information, though less clearly with open(name, "rb") as f: def get(struct_format): struct_format = "> " + struct_format file_bytes = f.read(struct.calcsize(struct_format)) return struct.unpack(struct_format, file_bytes) header, version, future_use = get("4s c 15s") counts = {} for name in ("ttisgmt", "ttisstd", "leap", "time", "type", "char"): counts[name] = get("l")[0] transitions = get("%sl" % counts["time"]) indices = get("%sB" % counts["time"]) ttinfo = [] for current in range(counts["type"]): ttinfo_struct = get("l?B") ttinfo.append(ttinfo_struct) abbreviations = get("%sc" % counts["char"]) index = 0 abbreviation_indices = {} for abbreviation in b"".join(abbreviations).split(b"\x00"): abbreviation_indices[index] = abbreviation.decode("us-ascii") index += len(abbreviation) + 1 for current, ttinfo_struct in enumerate(ttinfo): replacement = abbreviation_indices[ttinfo_struct[2]] ttinfo[current] = (ttinfo_struct[0], ttinfo_struct[1], replacement) offset, dst, abbreviation = ttinfo[0] tzinfo = [(None, offset, dst, abbreviation)] for transition, index in zip(transitions, indices): offset, dst, abbreviation = ttinfo[index] tzinfo.append((transition, offset, dst, abbreviation)) return tzinfo def window(seq, n=2): "Returns a sliding window (of width n) over data from the iterable" " s -> (s0,s1,...s[n-1]), (s1,s2,...,sn), ... " it = iter(seq) result = tuple(itertools.islice(it, n)) if len(result) == n: yield result for elem in it: result = result[1:] + (elem,) yield result def main(zone): import re regex_zone = re.compile("(?i)^[A-Z0-9_]+/[A-Z0-9_]+$") if regex_zone.match(zone): now = time.time() name = "/usr/share/zoneinfo/" + zone if not os.path.isfile(name): print("Unknown zone name") tzinfo = parse(name) for a, b in window(tzinfo): if now < (b[0] or 0): offset = a[1] / 3600 if not (offset % 1): offset = int(offset) print("%+d (%s)" % (offset, a[3])) return else: print("Not a valid zone name") if __name__ == "__main__": main(sys.argv[1])