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