jdk-24/test/jdk/java/util/TimeZone/tools/share/makeZoneData.pl
2024-03-05 19:32:29 +00:00

289 lines
7.8 KiB
Perl

#
# 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(<STDIN>) {
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 (<F>) {
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;
}