diff --git a/code/scripts/tzdata.py b/code/scripts/format_tzdata.py similarity index 51% rename from code/scripts/tzdata.py rename to code/scripts/format_tzdata.py index ae55802f..4de73ef0 100755 --- a/code/scripts/tzdata.py +++ b/code/scripts/format_tzdata.py @@ -1,10 +1,19 @@ import argparse import mmap import os -import pytz +import pathlib import re import sys +from importlib import resources + +import tzdata # https://tzdata.readthedocs.io/en/latest/ + + +def tzdata_version(): + return f"Generated with *{tzdata.IANA_VERSION=} {tzdata.__version__=}*" + + def maybe_fix_value(value): return re.sub(r"<[^>]*>", "UNK", value) @@ -27,11 +36,27 @@ def utc_alias(zone): ) -def zones(root): +def tzdata_resource_from_name(name): + pair = name.rsplit("/", 1) + if len(pair) == 1: + return resources.files("tzdata.zoneinfo") / pair[0] + + return resources.files(f'tzdata.zoneinfo.{pair[0].replace("/", ".")}') / pair[1] + + +def make_zones_list(zones): + with open(zones, "r") as f: + zones = [zone.strip() for zone in f.readlines()] + + return zones + + +def make_zones(args): out = [] - for zone in pytz.all_timezones_set: - with open(os.path.join(root, zone), "rb") as f: + for zone in make_zones_list(args.zones): + target = tzdata_resource_from_name(zone) + with tzdata_resource_from_name(zone).open("rb") as f: magic = f.read(4) if magic != b"TZif": continue @@ -50,7 +75,7 @@ def zones(root): return out -def table(zones): +def markdown(zones): utcs = [] rows = [] @@ -79,16 +104,40 @@ def table(zones): print() print("---") print() - print(f"Generated with *{pytz.OLSON_VERSION=} {pytz.VERSION=}*") + print(tzdata_version()) + + +def header(zones): + print(f"// ! ! ! DO NOT EDIT, AUTOMATICALLY GENERATED ! ! !") + print(f"// {tzdata_version()}") + print() + print("#pragma once") + print() + for name, value in zones: + print(f'#define\tTZ_{name.replace("/", "_")}\tPSTR("{value}")') if __name__ == "__main__": parser = argparse.ArgumentParser() + parser.add_argument( + "--format", + default="markdown", + choices=["markdown", "header"], + ) + parser.add_argument( + "--zones", + help="Zone names, one per line", + default=os.path.join(os.path.dirname(tzdata.__file__), "zones"), + ) parser.add_argument( "--root", help="Where do we get raw zoneinfo files from", - default=os.path.join(os.path.dirname(pytz.__file__), "zoneinfo"), + default=os.path.join(os.path.dirname(tzdata.__file__), "zoneinfo"), ) args = parser.parse_args() - table(zones(args.root)) + zones = make_zones(args) + if args.format == "markdown": + markdown(zones) + elif args.format == "header": + header(zones)