Skip to content

Instantly share code, notes, and snippets.

@mlouielu
Created February 27, 2024 16:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mlouielu/4acfb35b727b72c0683b9c32408e7e04 to your computer and use it in GitHub Desktop.
Save mlouielu/4acfb35b727b72c0683b9c32408e7e04 to your computer and use it in GitHub Desktop.
Parse tzfile for timezone information
import sys
import struct
import pathlib
def read_till_null(b, start):
end = start
while b[end] != 0:
end += 1
return b[start:end].decode("utf-8")
def main(tzfile_path: str):
"""python parse-tzfile.py /usr/share/zoneinfo/Asia/Taipei"""
tzfile = pathlib.Path(tzfile_path)
if not tzfile.exists():
print(f"File {tzfile_path} does not exist.")
sys.exit(1)
with tzfile.open("rb") as f:
# Headers
magic = f.read(4)
if magic != b"TZif":
print(f"File {tzfile_path} is not a valid tzfile.")
sys.exit(1)
version = f.read(1)
_ = f.read(15) # reserved
tzh_ttisutcnt = struct.unpack(">l", f.read(4))[0]
tzh_ttisstdcnt = struct.unpack(">l", f.read(4))[0]
tzh_leapcnt = struct.unpack(">l", f.read(4))[0]
tzh_timecnt = struct.unpack(">l", f.read(4))[0]
tzh_typecnt = struct.unpack(">l", f.read(4))[0]
tzh_charcnt = struct.unpack(">l", f.read(4))[0]
print(
tzh_ttisutcnt,
tzh_ttisstdcnt,
tzh_leapcnt,
tzh_timecnt,
tzh_typecnt,
tzh_charcnt,
)
# Timezone Data
tzh_transition_times = struct.unpack(
f"!{tzh_timecnt}l", f.read(4 * tzh_timecnt)
)
tzh_time_local_types = struct.unpack(
f"!{tzh_timecnt}B", f.read(1 * tzh_timecnt)
)
for tt in tzh_transition_times:
print(tt)
# Timezone Types
for i in range(tzh_typecnt):
tt_utoff = struct.unpack("!l", f.read(4))[0]
tt_isdst = struct.unpack(">B", f.read(1))[0]
tt_desigidx = struct.unpack(">B", f.read(1))[0]
print(tt_utoff, tt_isdst, tt_desigidx)
tzh_typechars = f.read(tzh_charcnt)
if __name__ == "__main__":
main(sys.argv[1])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment