update-tzdata.py revision 5d967e43d03e9c916548b9c290b0c4138df2f1f8
15d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes#!/usr/bin/python 2d40e63ee47e4a7f072a9d9a20e09c26f0090b02cElliott Hughes# Run with no arguments from any directory, with no special setup required. 3d40e63ee47e4a7f072a9d9a20e09c26f0090b02cElliott Hughes 45d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesimport ftplib 55d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesimport hashlib 65d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesimport os 75d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesimport re 85d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesimport shutil 95d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesimport string 105d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesimport subprocess 115d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesimport sys 125d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesimport tarfile 135d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesimport tempfile 145d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes 155d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes# Find the bionic directory, searching upward from this script. 165d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesbionic_libc_tools_zoneinfo_dir = os.path.realpath(os.path.dirname(sys.argv[0])) 175d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesbionic_libc_tools_dir = os.path.dirname(bionic_libc_tools_zoneinfo_dir) 185d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesbionic_libc_dir = os.path.dirname(bionic_libc_tools_dir) 195d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesbionic_dir = os.path.dirname(bionic_libc_dir) 205d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesbionic_libc_zoneinfo_dir = '%s/libc/zoneinfo' % bionic_dir 215d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesif not os.path.isdir(bionic_libc_tools_zoneinfo_dir) or not os.path.isdir(bionic_libc_zoneinfo_dir): 225d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes print "Couldn't find bionic/libc/tools/zoneinfo!" 235d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes sys.exit(1) 245d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesprint 'Found bionic in %s...' % bionic_dir 255d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes 265d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes 275d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesregions = ['africa', 'antarctica', 'asia', 'australasia', 'backward', 'etcetera', 'europe', 'factory', 'northamerica', 'southamerica'] 285d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes 295d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes 305d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesdef current_tzdata_version(): 315d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes return open('%s/zoneinfo.version' % bionic_libc_zoneinfo_dir).readline().rstrip('\n') 325d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes 335d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes 345d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesdef md5_file(filename): 355d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes md5 = hashlib.md5() 365d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes f = open(filename, 'rb') 375d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes while True: 385d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes data = f.read(8192) 395d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes if not data: 405d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes break 415d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes md5.update(data) 425d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes return md5.hexdigest() 435d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes 445d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes 455d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesdef upgrade_to(ftp, filename): 465d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes version = re.search('tzdata(.+)\.tar\.gz', filename).group(1) 475d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes 485d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes # Switch to a temporary directory. 495d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes tmp_dir = tempfile.mkdtemp('-tzdata') 505d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes os.chdir(tmp_dir) 515d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes print 'Created temporary directory "%s"...' % tmp_dir 525d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes 535d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes print 'Downloading %s...' % filename 545d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes ftp.retrbinary('RETR %s' % filename, open(filename, 'wb').write) 555d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes print 'MD5: %s' % md5_file(filename) 565d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes 575d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes print 'Extracting...' 585d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes os.mkdir('extracted') 595d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes tar = tarfile.open(filename, 'r') 605d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes tar.extractall('extracted') 615d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes 625d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes print 'Calling zic(1)...' 635d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes os.mkdir('data') 645d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes for region in regions: 655d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes if region != 'backward': 665d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes subprocess.check_call(['zic', '-d', 'data', 'extracted/%s' % region]) 675d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes 685d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes # Collect the data ZoneCompactor needs. 695d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes links = [] 705d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes zones = [] 715d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes for region in regions: 725d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes for line in open('extracted/%s' % region).readlines(): 735d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes fields = string.split(line) 745d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes if len(fields) == 0: 755d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes continue 765d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes elif fields[0] == 'Link': 775d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes links.append('%s %s %s\n' % (fields[0], fields[1], fields[2])) 785d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes zones.append(fields[2]) 795d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes elif fields[0] == 'Zone': 805d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes zones.append(fields[1]) 815d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes zones.sort() 825d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes 835d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes # Write it into the "setup" file. 845d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes setup = open('setup', 'w') 855d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes for link in links: 865d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes setup.write(link) 875d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes for zone in zones: 885d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes setup.write('%s\n' % zone) 895d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes setup.close() 905d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes 915d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes print 'Calling ZoneCompactor...' 925d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes subprocess.check_call(['javac', '-d', '.', 935d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes '%s/ZoneCompactor.java' % bionic_libc_tools_zoneinfo_dir, 945d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes '%s/ZoneInfo.java' % bionic_libc_tools_zoneinfo_dir]) 955d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes subprocess.check_call(['java', 'ZoneCompactor', 'setup', 'data']) 965d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes 975d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes print 'Updating bionic from %s to %s...' % (current_tzdata_version(), version) 985d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes # Move the .dat and .idx files... 995d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes os.remove('%s/zoneinfo.dat' % bionic_libc_zoneinfo_dir) 1005d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes shutil.move('zoneinfo.dat', bionic_libc_zoneinfo_dir) 1015d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes os.remove('%s/zoneinfo.idx' % bionic_libc_zoneinfo_dir) 1025d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes shutil.move('zoneinfo.idx', bionic_libc_zoneinfo_dir) 1035d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes # Write the .version file... 1045d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes zoneinfo_version = open('%s/zoneinfo.version' % bionic_libc_zoneinfo_dir, 'wb+') 1055d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes zoneinfo_version.write('%s\n' % version) 1065d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes zoneinfo_version.close() 1075d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes 108d40e63ee47e4a7f072a9d9a20e09c26f0090b02cElliott Hughes 109d40e63ee47e4a7f072a9d9a20e09c26f0090b02cElliott Hughes# URL from "Sources for Time Zone and Daylight Saving Time Data" 110d40e63ee47e4a7f072a9d9a20e09c26f0090b02cElliott Hughes# http://www.twinsun.com/tz/tz-link.htm 1115d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes 1125d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesprint 'Looking for new tzdata...' 1135d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesftp = ftplib.FTP('ftp.iana.org') 1145d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesftp.login() 1155d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesftp.cwd('tz/releases') 1165d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughestzdata_filenames = [] 1175d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesfor filename in ftp.nlst(): 1185d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes if filename.startswith('tzdata20'): 1195d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes tzdata_filenames.append(filename) 1205d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughestzdata_filenames.sort() 1215d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes 1225d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes# If you're several releases behind, we'll walk you through the upgrades one by one. 1235d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughescurrent_version = current_tzdata_version() 1245d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughescurrent_filename = 'tzdata%s.tar.gz' % current_version 1255d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesfor filename in tzdata_filenames: 1265d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes if filename > current_filename: 1275d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes upgrade_to(ftp, filename) 1285d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes sys.exit(0) 1295d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughes 1305d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughesprint 'You already have the latest tzdata (%s)!' % current_version 1315d967e43d03e9c916548b9c290b0c4138df2f1f8Elliott Hughessys.exit(0) 132