# # Program: make_timezonelist.pl # # Copyright 2003 Double Precision, Inc. See COPYING for # distribution information. # # Author: Sam Varshavchik # # # Original Author: Paul L. Allen # # Version: pla-0.1, 11-Aug-2003 # # Purpose: uses Olsen zoneinfo data to generate TIMEZONELIST # # OS: most recent release of *nix that include the Olsen TZ system. # # Warning: if you have updated the TZ source files without recompiling # then then some of the timezones generated by this program won't # work. But you wouldn't forget to recompile, would you? # # Copyright conditions: do whatever you want with it provided that if # you make changes and distribute the changed version you: # # 1) Replace the author with your contact details so I don't get people # asking me what's wrong with your changed version. # # 2) Add an "Original Author:" line with my contact details. # # 3) Change the version to be prefixed with your initials rather than # mine. # List of possible paths to the zoneinfo directory with the most common # cases first. Let me know if there are any others that should be included. @zoneinfo_dirs = qw ( /usr/share/zoneinfo /usr/local/etc/zoneinfo /usr/compat/linux/usr/share/zoneinfo /usr/share/lib/zoneinfo ); foreach $dir (@zoneinfo_dirs) { if (-d($dir)) { $zoneinfo_dir = $dir; last; } } die "Could not find a zoneinfo directory\n" unless ($zoneinfo_dir); if ( $^O eq "freebsd" ) { $iso3166tab = "/usr/share/misc/iso3166"; } elsif ( $^O eq "netbsd" ) { $iso3166tab = "/usr/share/misc/domains" } else { $iso3166tab = "$zoneinfo_dir/iso3166.tab"; } $zonetab = "$zoneinfo_dir/zone.tab"; $etc_dir = "$zoneinfo_dir/Etc"; $output = 'TIMEZONELIST'; open(ISO3166, $iso3166tab) || die "Could not open '$iso3166tab' for reading ($!)\n"; @lines = ; close(ISO3166); foreach $line (@lines) { next if ($line =~ /^\s*#/); next unless ($line =~ /\S/); chomp($line); if ( $^O eq "freebsd" ) { ($code, undef, undef, $country) = split(/\t/, $line, 4); } else { ($code, $country) = split(/\t/, $line, 2); } $countries{$code} = $country; } # Correct the entry for GB. $countries{GB} = 'United Kingdom'; if ( open(ZONES, $zonetab) == 0 ) { if ( $^O eq "netbsd" ) { 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"; } else { die "Could not open '$zonetab' for reading ($!)\n"; } } @lines = ; close(ZONES); foreach $line (@lines) { next if ($line =~ /^\s*#/); next unless ($line =~ /\S/); chomp($line); ($country_code, undef, $tz, $comment) = split(/\t/, $line, 4); $country = $countries{$country_code}; push(@zones, [lc($country), $tz, $country, $comment]); $longest_tz = length($tz) if (length($tz) > $longest_tz); } $num_tabs = int($longest_tz / 8) + 1; @sorted_zones = sort { $a->[0] cmp $b->[0] || $a->[3] cmp $b->[3] || $a cmp $b } @zones; open(OUT, ">$output") || die "Could not open '$output' for writing ($!)\n"; print OUT '*', "\t" x $num_tabs, "*\n"; foreach $zone (@sorted_zones) { if ($zone->[3]) { print OUT $zone->[1], "\t" x ($num_tabs - int(length($zone->[1]) / 8)), "$zone->[2]: $zone->[3]\n"; } else { print OUT $zone->[1], "\t" x ($num_tabs - int(length($zone->[1]) / 8)), "$zone->[2]\n"; } } # might not have zoneinfo/Etc on this machine so don't complain if it's # not there if (opendir(ETC, $etc_dir)) { @objects = readdir(ETC); closedir(ETC); foreach $object (@objects) { next unless ($object =~ /^GMT(.*)$/); next if ($1 =~ /^[+-]?0$/); if ($1) { push(@gmts, [$object, $1]); } else { $gmt_no_offset++; } } @sorted_gmts = sort {$b->[1] <=> $a->[1]} (@gmts); print OUT 'Etc/GMT', "\t" x $num_tabs, "GMT\n" if ($gmt_no_offset); foreach $gmt (@sorted_gmts) { $offset = $gmt->[1]; $abs_offset = abs($offset); $designator = "Etc/GMT$offset"; print OUT $designator, "\t" x ($num_tabs - int(length($designator) / 8)), "$abs_offset hour", ($abs_offset == 1 ? '' : 's'), ($offset < 0 ? ' ahead of' : ' behind'), " GMT\n";; } close(OUT); }