# # Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License version 2 only, as # published by the Free Software Foundation. # # This code is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # version 2 for more details (a copy is included in the LICENSE file that # accompanied this code). # # You should have received a copy of the GNU General Public License version # 2 along with this work; if not, write to the Free Software Foundation, # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. # # Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA # or visit www.oracle.com if you need additional information or have any # questions. # # # # # Perl script to generate ZoneData from Olson public time zone data. # # For J2SE before JDK1.3, see ../../README how to update TimeZone.java # static TimeZoneData. # For J2SE since JDK1.4, this script is used to generate testdata(reference) # for ZoneData.sh which is one of TimeZone Regression test. $continue = 0; # verbose flag $verbose = 0; # version of Olson's public zone information (e.g. "tzdata2000g") $versionName = "unknown"; # Number of testdata files. $count = 5; # Display name datafile $displayNameFile = "displaynames.txt"; # time zone IDs to be generated. If it's empty, then generate all time # zone in the tzdata files. @javatzids = (); # # Parses command-line options # while ($#ARGV >= 0) { if ($ARGV[0] =~ /^-v/) { $verbose = 1; } elsif ($ARGV[0] =~ /^-V/) { $versionName = $ARGV[1]; shift(@ARGV); } else { @javatzids = &readIDs($ARGV[0]); last; } shift(@ARGV); } # Beginning year of testdata ($sec, $min, $hour, $mday, $mon, $year, $wday, $ydat, $isdst) = gmtime(); $baseYear = $year+1900; if ($verbose == 1) { print STDERR "baseYear : $baseYear\n"; print STDERR "versionName : $versionName\n"; } # Open display name datafile open (DNFD, ">$displayNameFile") || die ("$displayNameFile : open error.\n"); while() { chop; if (/^\#/) { # skip comment line next; } @item = ("foo"); # Zone NAME GMTOFF RULES FORMAT [UNTIL] if ($continue == 1) { s/\#.*//; # chop trailing comments s/\s+$//; s/^\s+//; @item = split(/\s+/, $_); @item = ($zname, @item); # push zone name } elsif (/^Zone/) { s/\#.*//; # chop trailing comments s/\s+$//; @item = split(/\s+/, $_); $zname = $item[1]; if (defined ($zones{$name})) { printf STDERR "WARNING: duplicate definition of zone $name\n"; } shift(@item); } if (@item[0] ne "foo") { if($#item == 3) { # find out no UNTIL line $item[3] =~ s/%/%%/; $zones{$item[0]} = "Zone $item[0]\t$item[1]\t$item[2]\t$item[3]"; } else { $continue = 1; next; } } # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S if (/^Rule/) { ($rule, $name, $from, $to, $type, $in, $on, $at, $save, $letter) = split(/\s+/, $_); # matches specified year? for ($i = 0; $i < $count; $i++) { if ($from <= $baseYear+$i && ($to >= $baseYear+$i || $to eq "max") || ($from == $baseYear+$i && $to eq "only")) { if ($save ne "0") { $rules[$i]{$name . "0"} = $_; } else { $rules[$i]{$name . "1"} = $_; } } else { if ($from <= $baseYear) { if ($save ne "0") { $oldRules[0]{$name} = $_; } else { $oldRules[1]{$name} = $_; } } } } } $continue = 0; } # # Prepare output files # for ($i = 0, $fd = 0; $i < $count; $i++, $fd++) { $filename = "year".($baseYear+$i); open ($fd, ">$filename") || die ("$filename : open error.\n"); print $fd "# Based on $versionName\n"; } # # If no IDs are specified, produce test data for all zones. # if ($#javatzids < 0) { @javatzids = keys(%zones); } foreach $z (@javatzids) { # # skip any Riyadh zones; ZoneData.java can't handle Riyadh zones # # Skip these zones for CLDR # Africa/Windhoek: Negative DST (throughout year) # Korea zones: CLDR metazone shares Seoul/Pyongyang, where TZDB doesn't # Adak: CLDR's short names (Hawaii_Aleutian) differ from TZDB, HAST/HADT vs. HST/HDT # next if ($z =~ /Riyadh|Windhoek|Seoul|Pyongyang|Adak/); for ($i = 0, $fd = 0; $i < $count; $i++, $fd++) { if (!defined($zones{$z})) { printf $fd "$z ?\n"; printf STDERR "WARNING: java zone $z not found\n"; next; } @item = split(/\s+/, $zones{$z}); if ($item[3] ne "-") { printf $fd "$item[1] $item[2] "; if (defined($rules[$i]{$item[3] . "0"}) && defined($rules[$i]{$item[3] . "1"})) { $rule0 = $rules[$i]{$item[3] . "0"}; $rule1 = $rules[$i]{$item[3] . "1"}; @r0 = split(/\s+/, $rule0); @r1 = split(/\s+/, $rule1); printf $fd "$r0[5] $r0[6] $r0[7] $r1[5] $r1[6] $r1[7] $r0[8]\n"; printf $fd "$zones{$z}\n"; printf $fd "$rule0\n"; printf $fd "$rule1\n"; if ($i == 0) { $std = $dst = $item[4]; $std =~ s/%%s/$r1[9]/; if ($r1[9] eq "-") { $std =~ s/-//; } $dst =~ s/%%s/$r0[9]/; if ($r0[9] eq "-") { $dst =~ s/-//; } if ("$std$dst" =~ /[A-Z]/) { print DNFD "$item[1] $std $dst\n"; } } } else { printf $fd "-\n"; # In case we cannot find Rule, assume no DST. printf $fd "$zones{$z}\n"; printf STDERR "WARNING: $z no rules defined for $item[3]\n"; if ($i == 0) { # About 30 time zones (e.g. Asia/Tokyo needs the following # recovery. if ($item[4] =~ m/%/) { @r0 = split(/\s+/, $oldRules[0]{$item[3]}); @r1 = split(/\s+/, $oldRules[1]{$item[3]}); if ($i == 0) { $std = $dst = $item[4]; $std =~ s/%%s/$r1[9]/; if ($r1[9] eq "-") { $std =~ s/-//; } $dst =~ s/%%s/$r0[9]/; if ($r0[9] eq "-") { $dst =~ s/-//; } if ("$std$dst" =~ /[A-Z]/) { print DNFD "$item[1] $std $dst\n"; } } } else { if ("$item[4]" =~ /[A-Z]/) { print DNFD "$item[1] $item[4]\n"; } } } } } else { printf $fd "$item[1] $item[2] $item[3]\n"; printf $fd "$zones{$z}\n"; if ($i == 0 && "$item[4]" =~ /[A-Z]/) { print DNFD "$item[1] $item[4]\n"; } } } } # # Close all the output files # close (DNFD); for ($i = 0, $fd = 0; $i < $count; $i++, $fd++) { close ($fd); } # # Sort the displaynames.txt file # open my $fh, '<', $displayNameFile || die ("Can't open $displayNameFile for sorting\n");; chomp(my @names = <$fh>); close $fh; open my $fh, '>', $displayNameFile; foreach $line (sort @names) { print $fh $line,"\n"; } close $fh; exit(0); sub readIDs { local ($file) = @_; local (@ids, $i); open(F, $file) || die "Fatal: can't open $file.\n"; $i = 0; while () { chop; if (/^\#/) { # skip comment line next; } # trim any leading and trailing space s/^\s+//; s/\s+$//; if (/^\s*$/) { # skip blank line next; } $ids[$i++] = $_; } close(F); return @ids; }