1# 2# Program: make_timezonelist.pl 3# 4# Copyright 2003 Double Precision, Inc. See COPYING for 5# distribution information. 6# 7# Author: Sam Varshavchik <mrsam@courier-mta.com> 8# 9# $Id: sv-make_timezonelist.pl,v 1.4 2006/12/30 14:22:02 mrsam Exp $ 10# 11# Original Author: Paul L. Allen <pla@softflare.com> 12# 13# Version: pla-0.1, 11-Aug-2003 14# 15# Purpose: uses Olsen zoneinfo data to generate TIMEZONELIST 16# 17# OS: most recent release of *nix that include the Olsen TZ system. 18# 19# Warning: if you have updated the TZ source files without recompiling 20# then then some of the timezones generated by this program won't 21# work. But you wouldn't forget to recompile, would you? 22# 23# Copyright conditions: do whatever you want with it provided that if 24# you make changes and distribute the changed version you: 25# 26# 1) Replace the author with your contact details so I don't get people 27# asking me what's wrong with your changed version. 28# 29# 2) Add an "Original Author:" line with my contact details. 30# 31# 3) Change the version to be prefixed with your initials rather than 32# mine. 33 34 35# List of possible paths to the zoneinfo directory with the most common 36# cases first. Let me know if there are any others that should be included. 37@zoneinfo_dirs = qw 38( 39 /usr/share/zoneinfo 40 /usr/local/etc/zoneinfo 41 /usr/compat/linux/usr/share/zoneinfo 42 /usr/share/lib/zoneinfo 43); 44 45foreach $dir (@zoneinfo_dirs) 46{ 47 if (-d($dir)) 48 { 49 $zoneinfo_dir = $dir; 50 last; 51 } 52} 53die "Could not find a zoneinfo directory\n" unless ($zoneinfo_dir); 54if ( $^O eq "freebsd" ) 55{ 56 $iso3166tab = "/usr/share/misc/iso3166"; 57} 58elsif ( $^O eq "netbsd" ) 59{ 60 $iso3166tab = "/usr/share/misc/domains" 61} 62else 63{ 64 $iso3166tab = "$zoneinfo_dir/iso3166.tab"; 65} 66$zonetab = "$zoneinfo_dir/zone.tab"; 67$etc_dir = "$zoneinfo_dir/Etc"; 68 69$output = 'TIMEZONELIST'; 70 71open(ISO3166, $iso3166tab) || 72 die "Could not open '$iso3166tab' for reading ($!)\n"; 73@lines = <ISO3166>; 74close(ISO3166); 75 76foreach $line (@lines) 77{ 78 next if ($line =~ /^\s*#/); 79 next unless ($line =~ /\S/); 80 81 chomp($line); 82if ( $^O eq "freebsd" ) 83{ 84 ($code, undef, undef, $country) = split(/\t/, $line, 4); 85} 86else 87{ 88 ($code, $country) = split(/\t/, $line, 2); 89} 90 91 $countries{$code} = $country; 92} 93 94# Correct the entry for GB. 95$countries{GB} = 'United Kingdom'; 96 97if ( open(ZONES, $zonetab) == 0 ) 98{ 99 if ( $^O eq "netbsd" ) 100 { 101 die "Could not open '$zonetab' for reading ($!). Currently, NetBSD does not install zone.tab by default. You must manually fetch sharesrc.tgz from the source of your version and extract zone.tab into /usr/share/zoneinfo\n"; 102 } 103 else 104 { 105 die "Could not open '$zonetab' for reading ($!)\n"; 106 } 107} 108@lines = <ZONES>; 109close(ZONES); 110 111foreach $line (@lines) 112{ 113 next if ($line =~ /^\s*#/); 114 next unless ($line =~ /\S/); 115 116 chomp($line); 117 ($country_code, undef, $tz, $comment) = split(/\t/, $line, 4); 118 119 $country = $countries{$country_code}; 120 push(@zones, [lc($country), $tz, $country, $comment]); 121 $longest_tz = length($tz) if (length($tz) > $longest_tz); 122} 123 124$num_tabs = int($longest_tz / 8) + 1; 125 126@sorted_zones = sort 127 { 128 $a->[0] cmp $b->[0] || 129 $a->[3] cmp $b->[3] || 130 $a cmp $b 131 } @zones; 132 133open(OUT, ">$output") || 134 die "Could not open '$output' for writing ($!)\n"; 135 136print OUT '*', "\t" x $num_tabs, "*\n"; 137 138foreach $zone (@sorted_zones) 139{ 140 if ($zone->[3]) 141 { 142 print OUT $zone->[1], 143 "\t" x ($num_tabs - int(length($zone->[1]) / 8)), 144 "$zone->[2]: $zone->[3]\n"; 145 } 146 else 147 { 148 print OUT $zone->[1], 149 "\t" x ($num_tabs - int(length($zone->[1]) / 8)), 150 "$zone->[2]\n"; 151 } 152} 153 154# might not have zoneinfo/Etc on this machine so don't complain if it's 155# not there 156if (opendir(ETC, $etc_dir)) 157{ 158 @objects = readdir(ETC); 159 closedir(ETC); 160 161 foreach $object (@objects) 162 { 163 next unless ($object =~ /^GMT(.*)$/); 164 next if ($1 =~ /^[+-]?0$/); 165 166 if ($1) 167 { 168 push(@gmts, [$object, $1]); 169 } 170 else 171 { 172 $gmt_no_offset++; 173 } 174 } 175 176 @sorted_gmts = sort {$b->[1] <=> $a->[1]} (@gmts); 177 178 print OUT 'Etc/GMT', "\t" x $num_tabs, "GMT\n" if ($gmt_no_offset); 179 180 foreach $gmt (@sorted_gmts) 181 { 182 $offset = $gmt->[1]; 183 $abs_offset = abs($offset); 184 $designator = "Etc/GMT$offset"; 185 186 print OUT $designator, 187 "\t" x ($num_tabs - int(length($designator) / 8)), 188 "$abs_offset hour", 189 ($abs_offset == 1 ? '' : 's'), 190 ($offset < 0 ? ' ahead of' : ' behind'), 191 " GMT\n";; 192 } 193 194 close(OUT); 195} 196