|
Packit |
95306a |
#!/usr/bin/perl -w
|
|
Packit |
95306a |
# Copyright (c) 2008-2017 Sullivan Beck. All rights reserved.
|
|
Packit |
95306a |
# This program is free software; you can redistribute it and/or modify it
|
|
Packit |
95306a |
# under the same terms as Perl itself.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
###############################################################################
|
|
Packit |
95306a |
###############################################################################
|
|
Packit |
95306a |
# This script is used to automatically generate the Date::Manip::Zones
|
|
Packit |
95306a |
# and Date::Manip::TZ::_ZONE_ modules from the original time zone data.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
use lib "./lib";
|
|
Packit |
95306a |
use lib "./internal";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
require 5.010000;
|
|
Packit |
95306a |
use YAML;
|
|
Packit |
95306a |
use IO::File;
|
|
Packit |
95306a |
use Date::Manip::Base;
|
|
Packit |
95306a |
use Date::Manip::TZdata;
|
|
Packit |
95306a |
use strict;
|
|
Packit |
95306a |
use warnings;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
our $VERSION;
|
|
Packit |
95306a |
$VERSION='6.60';
|
|
Packit |
95306a |
|
|
Packit |
95306a |
our ($dmb);
|
|
Packit |
95306a |
$dmb = new Date::Manip::Base;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
our $curry = ( localtime(time) )[5] + 1900;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
##############################################################################
|
|
Packit |
95306a |
# GLOBAL VARIABLES
|
|
Packit |
95306a |
###############################################################################
|
|
Packit |
95306a |
|
|
Packit |
95306a |
our ($first_date,$last_date,$tzdata_src,$tzdata_dir,$tzdata_data,$tzdata_code,
|
|
Packit |
95306a |
$mod_dir,$off_dir,
|
|
Packit |
95306a |
$curr_year,$keep_year,$test_year,$zones_pm,$zones_pod,
|
|
Packit |
95306a |
%def_off,%nontzdata_zones,%def_alias2,%def_abbrev,%no_last,
|
|
Packit |
95306a |
%last_zone_offsets
|
|
Packit |
95306a |
);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# The first and last dates (UT) known by this module (everything in the
|
|
Packit |
95306a |
# 0001 - 9999 range except for the first and last 24 hours of that range).
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$first_date = "0001010200:00:00";
|
|
Packit |
95306a |
$last_date = "9999123100:00:00";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# The source for the tzdata/tzcode files:
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$tzdata_src = "ftp.iana.org";
|
|
Packit |
95306a |
$tzdata_dir = "tz";
|
|
Packit |
95306a |
$tzdata_data= "tzdata-latest.tar.gz";
|
|
Packit |
95306a |
$tzdata_code= "tzcode-latest.tar.gz";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
|
|
Packit |
95306a |
require "data.offset.pl";
|
|
Packit |
95306a |
require "data.abbrev.pl";
|
|
Packit |
95306a |
require "data.alias.pl";
|
|
Packit |
95306a |
require "data.misc.pl";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# so the CPAN indexer won't treat this as a POD file
|
|
Packit |
95306a |
our $podstr = '=pod';
|
|
Packit |
95306a |
our $hdstr = '=head1';
|
|
Packit |
95306a |
|
|
Packit |
95306a |
###############################################################################
|
|
Packit |
95306a |
# HELP
|
|
Packit |
95306a |
###############################################################################
|
|
Packit |
95306a |
|
|
Packit |
95306a |
our ($usage);
|
|
Packit |
95306a |
my $COM = $0;
|
|
Packit |
95306a |
$COM =~ s/^.*\///;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$usage=
|
|
Packit |
95306a |
"usage: $COM OPTIONS
|
|
Packit |
95306a |
-h/--help : Print help.
|
|
Packit |
95306a |
-v/--verbose : Increasing levels of verbosity
|
|
Packit |
95306a |
|
|
Packit |
95306a |
-a/--all : Do all steps
|
|
Packit |
95306a |
|
|
Packit |
95306a |
-f/--ftp : Download the tzdata/tzcode files from
|
|
Packit |
95306a |
the source and build the tools
|
|
Packit |
95306a |
-l/--list : Get a list of all time zones to dump
|
|
Packit |
95306a |
-d/--dump : This dumps out zone info for all of
|
|
Packit |
95306a |
the zones
|
|
Packit |
95306a |
-m/--mods : This creates the modules from the dumps
|
|
Packit |
95306a |
-o/--offset : Creates the offset modules
|
|
Packit |
95306a |
-z/--zones : Create the zones module
|
|
Packit |
95306a |
-c/--clean : Removes tzdata files
|
|
Packit |
95306a |
";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
###############################################################################
|
|
Packit |
95306a |
# PARSE ARGUMENTS
|
|
Packit |
95306a |
###############################################################################
|
|
Packit |
95306a |
|
|
Packit |
95306a |
our ($verbose);
|
|
Packit |
95306a |
$verbose = 0;
|
|
Packit |
95306a |
my $do_all = 0;
|
|
Packit |
95306a |
my $do_ftp = 0;
|
|
Packit |
95306a |
my $do_build = 0;
|
|
Packit |
95306a |
my $do_list = 0;
|
|
Packit |
95306a |
my $do_dump = 0;
|
|
Packit |
95306a |
my $do_mods = 0;
|
|
Packit |
95306a |
my $do_off = 0;
|
|
Packit |
95306a |
my $do_zones = 0;
|
|
Packit |
95306a |
my $do_clean = 0;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
while ($_ = shift) {
|
|
Packit |
95306a |
|
|
Packit |
95306a |
(print $usage), exit if ($_ eq "-h" || $_ eq "--help");
|
|
Packit |
95306a |
$verbose = 1, next if ($_ eq "-v" || $_ eq "--verbose");
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$do_all = 1, next if ($_ eq "-a" || $_ eq "--all");
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$do_ftp = 1, next if ($_ eq "-f" || $_ eq "--ftp");
|
|
Packit |
95306a |
$do_build = 1, next if ($_ eq "-b" || $_ eq "--build");
|
|
Packit |
95306a |
$do_list = 1, next if ($_ eq "-l" || $_ eq "--list");
|
|
Packit |
95306a |
$do_dump = 1, next if ($_ eq "-d" || $_ eq "--dump");
|
|
Packit |
95306a |
$do_mods = 1, next if ($_ eq "-m" || $_ eq "--mods");
|
|
Packit |
95306a |
$do_off = 1, next if ($_ eq "-o" || $_ eq "--offset");
|
|
Packit |
95306a |
$do_zones = 1, next if ($_ eq "-z" || $_ eq "--zones");
|
|
Packit |
95306a |
$do_clean = 1, next if ($_ eq "-c" || $_ eq "--clean");
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
############################################################################
|
|
Packit |
95306a |
# MAIN PROGRAM
|
|
Packit |
95306a |
############################################################################
|
|
Packit |
95306a |
|
|
Packit |
95306a |
do_ftp() if ($do_all || $do_ftp);
|
|
Packit |
95306a |
do_build() if ($do_all || $do_build);
|
|
Packit |
95306a |
do_list() if ($do_all || $do_list);
|
|
Packit |
95306a |
do_dump() if ($do_all || $do_dump);
|
|
Packit |
95306a |
do_mods() if ($do_all || $do_mods);
|
|
Packit |
95306a |
do_off() if ($do_all || $do_off);
|
|
Packit |
95306a |
do_zones() if ($do_all || $do_zones);
|
|
Packit |
95306a |
do_clean() if ( $do_clean);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
############################################################################
|
|
Packit |
95306a |
# DO_FTP
|
|
Packit |
95306a |
############################################################################
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# FTP the tzdata/tzcode packages
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
sub do_ftp {
|
|
Packit |
95306a |
print "FTP...\n";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
system("rm -rf tzdata; mkdir tzdata");
|
|
Packit |
95306a |
chdir("tzdata");
|
|
Packit |
95306a |
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# Get the tz*latest.tar.gz links to determine the versions
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
|
|
Packit |
95306a |
system("wget -q 'ftp://$tzdata_src/$tzdata_dir/$tzdata_data' " .
|
|
Packit |
95306a |
"'ftp://$tzdata_src/$tzdata_dir/$tzdata_code'");
|
|
Packit |
95306a |
if (! -f $tzdata_data) {
|
|
Packit |
95306a |
die "ERROR: unable to ftp data. Try again later.";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
if (! -f $tzdata_code) {
|
|
Packit |
95306a |
die "ERROR: unable to ftp code. Try again later.";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
system("tar xzf $tzdata_data");
|
|
Packit |
95306a |
my $tzdata_vers = _release('data');
|
|
Packit |
95306a |
|
|
Packit |
95306a |
system("tar xzf $tzdata_code");
|
|
Packit |
95306a |
my $tzcode_vers = _release('code');
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print " TZdata : $tzdata_vers\n";
|
|
Packit |
95306a |
print " Tzcode : $tzcode_vers\n";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
system("echo $tzdata_vers > _version; " .
|
|
Packit |
95306a |
"echo $tzcode_vers >> _version; ");
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
sub _release {
|
|
Packit |
95306a |
my($type) = @_;
|
|
Packit |
95306a |
if (! -f 'NEWS') {
|
|
Packit |
95306a |
die "ERROR: unable to determine version (no NEWS): $type\n";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
my $vers = `grep Release NEWS | head -1 | awk '{print \$2}'`;
|
|
Packit |
95306a |
chomp($vers);
|
|
Packit |
95306a |
if ($vers !~ /^\d\d\d\d[a-z]$/) {
|
|
Packit |
95306a |
die "ERROR: uknown version format: $type: $vers\n";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
system("mv NEWS NEWS.$type");
|
|
Packit |
95306a |
return $vers;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Build the package
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
sub do_build {
|
|
Packit |
95306a |
print "Build...\n";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
system("cd tzdata; " .
|
|
Packit |
95306a |
"touch NEWS; " .
|
|
Packit |
95306a |
"make TOPDIR=./tmp INSTALL;");
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
############################################################################
|
|
Packit |
95306a |
# DO_LIST
|
|
Packit |
95306a |
############################################################################
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Get a list of all zones in the tzdata files which we will create
|
|
Packit |
95306a |
# modules for. Store a list of them and the associated module name.
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# Stored in: _zone
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
sub do_list {
|
|
Packit |
95306a |
print "List...\n";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# Get a list of zones from all Zone lines in the standard files in
|
|
Packit |
95306a |
# the tzdata package.
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my(@zone);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
foreach my $file (@Date::Manip::TZdata::StdFiles) {
|
|
Packit |
95306a |
my @tmp = `grep '^Zone' tzdata/$file | awk '{print \$2}'`;
|
|
Packit |
95306a |
chomp(@tmp);
|
|
Packit |
95306a |
push(@zone,@tmp);
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# Generate a module name for every zone (excepting some which
|
|
Packit |
95306a |
# we're ignoring, or creating in other ways).
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my %module = ();
|
|
Packit |
95306a |
my %modname = ();
|
|
Packit |
95306a |
my %alias = ();
|
|
Packit |
95306a |
foreach my $zone (sort @zone) {
|
|
Packit |
95306a |
next if (exists $nontzdata_zones{$zone} ||
|
|
Packit |
95306a |
exists $def_alias2{$zone});
|
|
Packit |
95306a |
my $module = _do_list_modname(\%modname,$zone);
|
|
Packit |
95306a |
$module{$zone} = [ $module, "tzdata" ];
|
|
Packit |
95306a |
$alias{$zone} = [ $zone, "tzdata" ];
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# Generate a module name for every zone which is created as
|
|
Packit |
95306a |
# an offset (e.g. GMT-3).
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
|
|
Packit |
95306a |
foreach my $zone (sort keys %nontzdata_zones) {
|
|
Packit |
95306a |
my($type,$val) = @{ $nontzdata_zones{$zone} };
|
|
Packit |
95306a |
if ($type eq "offset") {
|
|
Packit |
95306a |
my $module = _do_list_modname(\%modname,$zone);
|
|
Packit |
95306a |
$module{$zone} = [ $module, "offset", $val ];
|
|
Packit |
95306a |
$alias{$zone} = [ $zone, "offset" ];
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# Handle all other special cases such as special aliases and
|
|
Packit |
95306a |
# ignored zones.
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
|
|
Packit |
95306a |
foreach my $zone (sort keys %nontzdata_zones) {
|
|
Packit |
95306a |
my($type,$val) = @{ $nontzdata_zones{$zone} };
|
|
Packit |
95306a |
if ($type eq "offset") {
|
|
Packit |
95306a |
next;
|
|
Packit |
95306a |
} elsif ($type eq "alias") {
|
|
Packit |
95306a |
warn "[do_list] unknown alias [$zone: $val]\n"
|
|
Packit |
95306a |
if (! exists $module{$val});
|
|
Packit |
95306a |
$alias{$zone} = [ $val, $type ];
|
|
Packit |
95306a |
} elsif ($type eq "ignore") {
|
|
Packit |
95306a |
$alias{$zone} = [ $val, $type ];
|
|
Packit |
95306a |
} else {
|
|
Packit |
95306a |
warn "[do_list] unknown type [$zone: $type]\n";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Write out the official list of zones and aliases.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_yaml_write(\%module,"tzdata/_zone_list",0);
|
|
Packit |
95306a |
_yaml_write(\%alias, "tzdata/_alias_list",0);
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Takes a hashref $module{MODNAME} = ZONE and a zone and comes up
|
|
Packit |
95306a |
# with a unique module name for it. It returns the name of the module
|
|
Packit |
95306a |
# (as well as adds it to the hash).
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
sub _do_list_modname {
|
|
Packit |
95306a |
my($modnames,$zone) = @_;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my $modname = "";
|
|
Packit |
95306a |
if ($zone =~ /\//) {
|
|
Packit |
95306a |
my @tmp = split(/\//,$zone);
|
|
Packit |
95306a |
$modname = substr($tmp[0],0,2) . substr($tmp[$#tmp],0,4);
|
|
Packit |
95306a |
} else {
|
|
Packit |
95306a |
$modname = substr($zone,0,6);
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
$modname =~ s/\-/m/g;
|
|
Packit |
95306a |
$modname =~ s/\+/p/g;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my $i = "00";
|
|
Packit |
95306a |
while (exists $$modnames{"$modname$i"}) {
|
|
Packit |
95306a |
$i++;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
$modname .= $i;
|
|
Packit |
95306a |
$$modnames{$modname} = 1;
|
|
Packit |
95306a |
return lc($modname);
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
############################################################################
|
|
Packit |
95306a |
# DO_DUMP
|
|
Packit |
95306a |
############################################################################
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Dump every zone.
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# Stored in: dump/MODNAME
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
sub do_dump {
|
|
Packit |
95306a |
print "Dump...\n";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my $tmp = _yaml_read("tzdata/_zone_list");
|
|
Packit |
95306a |
my %module = %$tmp;
|
|
Packit |
95306a |
my $num = keys %module;
|
|
Packit |
95306a |
my $len = length($num);
|
|
Packit |
95306a |
my $i = 0;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
system("rm -rf tzdata/dump; " .
|
|
Packit |
95306a |
"mkdir tzdata/dump");
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print " dumping "," "x($len-length($i)),"$i / $num";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
foreach my $zone (keys %module) {
|
|
Packit |
95306a |
$i++;
|
|
Packit |
95306a |
print "\010"x($len*2+3)," "x($len-length($i)),"$i / $num";
|
|
Packit |
95306a |
my($module,$type) = @{ $module{$zone} };
|
|
Packit |
95306a |
next if ($type ne "tzdata");
|
|
Packit |
95306a |
system("cd tzdata; " .
|
|
Packit |
95306a |
"tmp/etc/zdump -c $test_year -v $zone > dump/$module");
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
print "\n";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
############################################################################
|
|
Packit |
95306a |
# DO_MODS
|
|
Packit |
95306a |
############################################################################
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Creates the modules.
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
sub do_mods {
|
|
Packit |
95306a |
print "Modules...\n";
|
|
Packit |
95306a |
my $tzd = Date::Manip::TZdata->new();
|
|
Packit |
95306a |
system("rm -f $mod_dir/*");
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my $zone_list = _yaml_read("tzdata/_zone_list");
|
|
Packit |
95306a |
my %zone_list = %$zone_list;
|
|
Packit |
95306a |
my $num = keys %zone_list;
|
|
Packit |
95306a |
my $len = length($num);
|
|
Packit |
95306a |
my $i = 0;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my $abbrev = {};
|
|
Packit |
95306a |
my $data = {};
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print " module "," "x($len-length($i)),"$i / $num";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
foreach my $zone (keys %zone_list) {
|
|
Packit |
95306a |
$i++;
|
|
Packit |
95306a |
print "\010"x($len*2+3)," "x($len-length($i)),"$i / $num";
|
|
Packit |
95306a |
my($module,$type,@args) = @{ $zone_list{$zone} };
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if ($type eq "tzdata") {
|
|
Packit |
95306a |
_do_mods_tzdata($tzd,$abbrev,$data,$zone,$module,@args);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
} elsif ($type eq "offset") {
|
|
Packit |
95306a |
_do_mods_offset($tzd,$abbrev,$data,$zone,$module,@args);
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
print "\n";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# $data now contains a hash of:
|
|
Packit |
95306a |
# YEAR => [ TYPE, VAL1, VAL2, ... ]
|
|
Packit |
95306a |
# where TYPE is currently blank.
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# VALi is a reference to a time change [ ABB, OFFSET, ISDST ]
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# TYPE will be set to one of the following:
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# std0, : a standard year is one with two time changes which must
|
|
Packit |
95306a |
# std1 be with ISDST = 1 and 0, and both must be integers
|
|
Packit |
95306a |
# that differ by exactly 1. If the ISDST = 0 comes first,
|
|
Packit |
95306a |
# it is set to std0. Otherwise it is set to std1.
|
|
Packit |
95306a |
# last0,
|
|
Packit |
95306a |
# last1 : if it's a standard year AND the year is after $keep_year
|
|
Packit |
95306a |
# end : a non-standard year after $keep_year
|
|
Packit |
95306a |
# non : a non-standard year before $keep_year
|
|
Packit |
95306a |
|
|
Packit |
95306a |
foreach my $zone (keys %$data) {
|
|
Packit |
95306a |
my $lasttype = '';
|
|
Packit |
95306a |
foreach my $year (keys %{ $$data{$zone} }) {
|
|
Packit |
95306a |
my $type;
|
|
Packit |
95306a |
my @tmp = @{ $$data{$zone}{$year} };
|
|
Packit |
95306a |
shift(@tmp);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Standard times must have two changes
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$type = 'std';
|
|
Packit |
95306a |
$type = 'non' if (@tmp != 2);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Standard times must have both offsets on the hour.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my ($off1,$off2);
|
|
Packit |
95306a |
if ($type eq 'std') {
|
|
Packit |
95306a |
$off1 = $tmp[0][1];
|
|
Packit |
95306a |
$off2 = $tmp[1][1];
|
|
Packit |
95306a |
if ($off1 !~ /:00:00$/ ||
|
|
Packit |
95306a |
$off2 !~ /:00:00$/) {
|
|
Packit |
95306a |
$type = 'non';
|
|
Packit |
95306a |
} else {
|
|
Packit |
95306a |
$type = 'std';
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Standard times must have offsets that are 1 hour apart.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if ($type eq 'std') {
|
|
Packit |
95306a |
$off1 =~ s/:00:00$//;
|
|
Packit |
95306a |
$off2 =~ s/:00:00$//;
|
|
Packit |
95306a |
$type = 'non' if (abs($off1 - $off2) != 1);
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Standard times have offsets with two offsets with ISDST = 0 and 1
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my $std;
|
|
Packit |
95306a |
if ($type eq 'std' &&
|
|
Packit |
95306a |
$tmp[0][2] == 1 &&
|
|
Packit |
95306a |
$tmp[1][2] == 0) {
|
|
Packit |
95306a |
$std = 1;
|
|
Packit |
95306a |
} elsif ($type eq 'std' &&
|
|
Packit |
95306a |
$tmp[0][2] == 0 &&
|
|
Packit |
95306a |
$tmp[1][2] == 1) {
|
|
Packit |
95306a |
$std = 0;
|
|
Packit |
95306a |
} else {
|
|
Packit |
95306a |
$type = 'non';
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Set the type
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if ($type eq 'std') {
|
|
Packit |
95306a |
if ($year > $keep_year) {
|
|
Packit |
95306a |
$type = "last$std";
|
|
Packit |
95306a |
} else {
|
|
Packit |
95306a |
$type .= $std;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
} elsif ($year > $keep_year) {
|
|
Packit |
95306a |
$type = 'end';
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# We'll discard the very last year of a standard timezone
|
|
Packit |
95306a |
# because they end on the first change of a year instead of
|
|
Packit |
95306a |
# the second.
|
|
Packit |
95306a |
next if ($lasttype =~ /last/ && $type eq 'end');
|
|
Packit |
95306a |
$lasttype = $type;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$$data{$zone}{$year}[0] = $type;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Create a list of all EST5EDT style time zone aliases.
|
|
Packit |
95306a |
# These only apply during standard years.
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# Also, we will ignore aliases when the abbreviations are
|
|
Packit |
95306a |
# offsets.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my $alias2 = {};
|
|
Packit |
95306a |
ZONE: foreach my $zone (keys %$data) {
|
|
Packit |
95306a |
foreach my $year (sort keys %{ $$data{$zone} }) {
|
|
Packit |
95306a |
my ($type,@tmp) = @{ $$data{$zone}{$year} };
|
|
Packit |
95306a |
next if ($type ne 'std0' &&
|
|
Packit |
95306a |
$type ne 'std1' &&
|
|
Packit |
95306a |
$type ne 'last0' &&
|
|
Packit |
95306a |
$type ne 'last1');
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# The format is
|
|
Packit |
95306a |
# STDABB STDOFFHR DSTABB
|
|
Packit |
95306a |
# where STDABB and DSTABB are the abbreviations, and STDOFFHR
|
|
Packit |
95306a |
# is the offset for standard time as an integer negated.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my ($stdabb,$dstabb,$stdoff);
|
|
Packit |
95306a |
if ($type eq 'std0' || $type eq 'last0') {
|
|
Packit |
95306a |
$stdabb = $tmp[0][0];
|
|
Packit |
95306a |
$dstabb = $tmp[1][0];
|
|
Packit |
95306a |
$stdoff = $tmp[0][1];
|
|
Packit |
95306a |
} else {
|
|
Packit |
95306a |
$stdabb = $tmp[1][0];
|
|
Packit |
95306a |
$dstabb = $tmp[0][0];
|
|
Packit |
95306a |
$stdoff = $tmp[1][1];
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
$stdoff =~ s/:00:00$//;
|
|
Packit |
95306a |
$stdoff *= -1;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
next if ($stdabb =~ /^[+-]?\d+$/ ||
|
|
Packit |
95306a |
$dstabb =~ /^[+-]?\d+$/);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my $alias = "${stdabb}${stdoff}${dstabb}";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if ($type eq 'last0' || $type eq 'last1') {
|
|
Packit |
95306a |
_do_mods_years($alias2,$zone,$alias,$year,9999);
|
|
Packit |
95306a |
next ZONE;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
_do_mods_years($alias2,$zone,$alias,$year,$year);
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_yaml_write($data, 'tzdata/_data',0);
|
|
Packit |
95306a |
_yaml_write($alias2,'tzdata/_alias2_un',0);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$abbrev = _order_elements($abbrev);
|
|
Packit |
95306a |
$alias2 = _order_elements($alias2);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_yaml_write($abbrev,'tzdata/_abbrev_or',0);
|
|
Packit |
95306a |
_yaml_write($alias2,'tzdata/_alias2_or',0);
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# This creates a module from a tzdata dump.
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
sub _do_mods_tzdata {
|
|
Packit |
95306a |
my($tzd,$abbrev,$data,$zone,$module) = @_;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my @lines = `cat tzdata/dump/$module`;
|
|
Packit |
95306a |
chomp(@lines);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
while (@lines && $lines[0] =~ /NULL$/) {
|
|
Packit |
95306a |
shift(@lines);
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
while (@lines && $lines[$#lines] =~ /NULL$/) {
|
|
Packit |
95306a |
pop(@lines);
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if (! @lines) {
|
|
Packit |
95306a |
warn "[_do_mods_tzdata] empty zone [$zone]\n";
|
|
Packit |
95306a |
return;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Check the format of every line
|
|
Packit |
95306a |
my $err = _do_mods_tzdata_check($zone,@lines);
|
|
Packit |
95306a |
return if ($err);
|
|
Packit |
95306a |
_do_mods_tzdata_mod($tzd,$abbrev,$data,$zone,$module,@lines);
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# This checks every line in a zdump file to make sure it is the
|
|
Packit |
95306a |
# correct format.
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
sub _do_mods_tzdata_check {
|
|
Packit |
95306a |
my($zone,@lines) = @_;
|
|
Packit |
95306a |
my($dow) = '(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)';
|
|
Packit |
95306a |
my($mon) = '(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)';
|
|
Packit |
95306a |
my($dom) = '(?:\d+)';
|
|
Packit |
95306a |
my($time) = '(?:\d\d:\d\d:\d\d)';
|
|
Packit |
95306a |
my($year) = '(?:\d\d\d\d)';
|
|
Packit |
95306a |
my($drx) = qr/$dow\s+$mon\s+$dom\s+$time\s+$year/;
|
|
Packit |
95306a |
my($rx) = qr/\Q$zone\E\s+$drx\s+UT\s+=\s+$drx\s+\S+\s+isdst=[01]\s+gmtoff=\-?\d+$/;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my($err) = 0;
|
|
Packit |
95306a |
foreach my $line (@lines) {
|
|
Packit |
95306a |
if ($line !~ /$rx/) {
|
|
Packit |
95306a |
warn "[_do_mods_tzdata] invalid line [$zone]\n $line\n";
|
|
Packit |
95306a |
$err = 1;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
return $err;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
sub _do_mods_tzdata_mod {
|
|
Packit |
95306a |
my($tzd,$abbrev,$data,$zone,$module,@lines) = @_;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
###
|
|
Packit |
95306a |
### Analyze the dump file and store information about all
|
|
Packit |
95306a |
### time zone periods in a list. A time zone period is a
|
|
Packit |
95306a |
### starting time and ending time during which the abbreviation,
|
|
Packit |
95306a |
### offset, and ISDST values remain unchanged.
|
|
Packit |
95306a |
###
|
|
Packit |
95306a |
### The first line in the dump file defines when the pre-use
|
|
Packit |
95306a |
### period (i.e. the period of time before the time zone was
|
|
Packit |
95306a |
### actually defined) ended.
|
|
Packit |
95306a |
###
|
|
Packit |
95306a |
### After the first line, all lines (except the last one) appear as
|
|
Packit |
95306a |
### pairs. The first one tells the time when a new time zone period
|
|
Packit |
95306a |
### starts (which should be exactly 1 second after the previous
|
|
Packit |
95306a |
### period ended) and the second line tells when the period ends.
|
|
Packit |
95306a |
###
|
|
Packit |
95306a |
### The last line defines the start of a new period that doesn't
|
|
Packit |
95306a |
### have an end defined. If the year is after $keep_year, then
|
|
Packit |
95306a |
### the period switches to LASTRULE handline. If it is before
|
|
Packit |
95306a |
### $keep_year, then the time zone stopped doing DST changes and
|
|
Packit |
95306a |
### stay in the same period for good.
|
|
Packit |
95306a |
###
|
|
Packit |
95306a |
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# Parse the first dump line to determine the end of the
|
|
Packit |
95306a |
# pre-zone period.
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my @dates;
|
|
Packit |
95306a |
my $last = 1; # Whether or not to do LAST RULE
|
|
Packit |
95306a |
my ($year,$year2);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my $line = shift(@lines);
|
|
Packit |
95306a |
my($dowU,$monU,$domU,$timeU,$yearU,$dowL,$monL,$domL,$timeL,$yearL,
|
|
Packit |
95306a |
$abb,$isdst) = _do_mods_splitdump($line);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if ($isdst) {
|
|
Packit |
95306a |
warn "[_do_mods_tzdata] first line in DST [$zone]\n";
|
|
Packit |
95306a |
return 1;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# Calculate the offset of the pre-zone period.
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my @endUT = ($yearU,$monU,$domU,@{ $dmb->split("time",$timeU) });
|
|
Packit |
95306a |
my @endLT = ($yearL,$monL,$domL,@{ $dmb->split("time",$timeL) });
|
|
Packit |
95306a |
my @offset = @{ $dmb->calc_date_date(\@endUT,\@endLT) };
|
|
Packit |
95306a |
my $offset = $dmb->join("offset",\@offset);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if ($offset eq "" ||
|
|
Packit |
95306a |
$abb eq "" ||
|
|
Packit |
95306a |
$isdst eq "") {
|
|
Packit |
95306a |
warn "[_do_mods_tzdata] blank value in zone [$zone, @endUT]\n";
|
|
Packit |
95306a |
return 1;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# The pre-zone period starts on Jan 2 0001 at 00:00:00 and
|
|
Packit |
95306a |
# ends at the time from the first dump line.
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my @begUT = @{ $dmb->split("date",$first_date) };
|
|
Packit |
95306a |
my @begLT = @{ $dmb->calc_date_time(\@begUT,\@offset) };
|
|
Packit |
95306a |
@dates = ("0001",[@begUT],[@begLT],$offset,[@offset],
|
|
Packit |
95306a |
$abb,$isdst,[@endUT],[@endLT]);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$year2 = $endUT[0];
|
|
Packit |
95306a |
_do_mods_years($abbrev,$zone,$abb,"0001",$year2) if ($abb !~ /^[+-]?\d*$/);
|
|
Packit |
95306a |
$$data{$zone}{"0001"} = [ '', [$abb,$offset,$isdst] ];
|
|
Packit |
95306a |
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# Parse every pair of dump lines.
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
|
|
Packit |
95306a |
while (@lines) {
|
|
Packit |
95306a |
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# The first line is the start of the period
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$line = shift(@lines);
|
|
Packit |
95306a |
($dowU,$monU,$domU,$timeU,$yearU,$dowL,$monL,$domL,$timeL,$yearL,
|
|
Packit |
95306a |
$abb,$isdst) = _do_mods_splitdump($line);
|
|
Packit |
95306a |
$year = $yearU;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
@begUT = ($yearU,$monU,$domU,@{ $dmb->split("time",$timeU) });
|
|
Packit |
95306a |
@begLT = ($yearL,$monL,$domL,@{ $dmb->split("time",$timeL) });
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my @tmp = @{ $dmb->calc_date_time(\@endUT,[0,0,1]) };
|
|
Packit |
95306a |
if ($dmb->cmp(\@tmp,\@begUT) != 0) {
|
|
Packit |
95306a |
warn "[_do_mods_tzdata] invalid start in zone [$zone, @begUT]\n";
|
|
Packit |
95306a |
return 1;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
@offset = @{ $dmb->calc_date_date(\@begUT,\@begLT) };
|
|
Packit |
95306a |
$offset = $dmb->join("offset",\@offset);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if ($offset eq "" ||
|
|
Packit |
95306a |
$abb eq "" ||
|
|
Packit |
95306a |
$isdst eq "") {
|
|
Packit |
95306a |
warn "[_do_mods_tzdata] blank value in zone [$zone, @begUT]\n";
|
|
Packit |
95306a |
return 1;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# If a second line exists, it is the end of the period.
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# If no second line exists, then either we need to switch to
|
|
Packit |
95306a |
# LAST RULE behavior (if the year of the first line is after
|
|
Packit |
95306a |
# $keep_year), or the zone abandoned doing daylight savings
|
|
Packit |
95306a |
# time and this line reflects the time until 9999.
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if (@lines) {
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# A second line marks the end of the period
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my ($a,$i);
|
|
Packit |
95306a |
$line = shift(@lines);
|
|
Packit |
95306a |
($dowU,$monU,$domU,$timeU,$yearU,$dowL,$monL,$domL,$timeL,$yearL,
|
|
Packit |
95306a |
$a,$i) = _do_mods_splitdump($line);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
@endUT = ($yearU,$monU,$domU,@{ $dmb->split("time",$timeU) });
|
|
Packit |
95306a |
@endLT = ($yearL,$monL,$domL,@{ $dmb->split("time",$timeL) });
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my @o = @{ $dmb->calc_date_date(\@endUT,\@endLT) };
|
|
Packit |
95306a |
my $o = $dmb->join("offset",\@o);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if ($o eq "" ||
|
|
Packit |
95306a |
$a eq "" ||
|
|
Packit |
95306a |
$i eq "") {
|
|
Packit |
95306a |
warn "[_do_mods_tzdata] blank value in zone [$zone, @endUT]\n";
|
|
Packit |
95306a |
return 1;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if ($o ne $offset ||
|
|
Packit |
95306a |
$a ne $abb ||
|
|
Packit |
95306a |
$i ne $isdst) {
|
|
Packit |
95306a |
warn "[_do_mods_tzdata] invalid value in zone [$zone, @endUT]\n";
|
|
Packit |
95306a |
return 1;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
} elsif ($year > $keep_year &&
|
|
Packit |
95306a |
! exists $no_last{$zone}) {
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# If it's a single line after $keep_year, then it's the start
|
|
Packit |
95306a |
# of a regular LAST RULE style time change. Discard it... we'll
|
|
Packit |
95306a |
# use the LAST RULE to come up with those periods.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
last;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
} else {
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# A single line before $keep_year means that the time zone
|
|
Packit |
95306a |
# stopped doing DST stuff, and switched to a single offset.
|
|
Packit |
95306a |
# There is no LAST RULE in this case.
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# This will also apply to zones which do not use the LAST
|
|
Packit |
95306a |
# RULE method.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
@endUT = @{ $dmb->split("date",$last_date) };
|
|
Packit |
95306a |
@endLT = @{ $dmb->calc_date_time(\@endUT,\@offset) };
|
|
Packit |
95306a |
$last = 0;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Now store the data for this time zone period
|
|
Packit |
95306a |
|
|
Packit |
95306a |
push(@dates,$year,[@begUT],[@begLT],$offset,[@offset],$abb,$isdst,[@endUT],[@endLT]);
|
|
Packit |
95306a |
$year2 = $endUT[0];
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if (exists $$data{$zone}{$year}) {
|
|
Packit |
95306a |
push(@{ $$data{$zone}{$year} },[$abb,$offset,$isdst]);
|
|
Packit |
95306a |
} else {
|
|
Packit |
95306a |
$$data{$zone}{$year} = [ '', [$abb,$offset,$isdst] ];
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_do_mods_years($abbrev,$zone,$abb,$year,$year2) if ($abb !~ /^[+-]?\d*$/);
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
###
|
|
Packit |
95306a |
### Now we'll analyze all the critical dates. Three different things
|
|
Packit |
95306a |
### will occur:
|
|
Packit |
95306a |
###
|
|
Packit |
95306a |
### 1) For years < $keep_year, the data will simply get stored in
|
|
Packit |
95306a |
### the module.
|
|
Packit |
95306a |
### 2) For year = $keep_year, the data will be stored in the module
|
|
Packit |
95306a |
### and used to determine how LAST RULE critical dates are
|
|
Packit |
95306a |
### determined.
|
|
Packit |
95306a |
### 3) For year > $keep_year, critical dates will not be stored, but
|
|
Packit |
95306a |
### will be tested to make sure they are consistant with the methods
|
|
Packit |
95306a |
### determined in 2). However, this step will be elsewhere. I will
|
|
Packit |
95306a |
### use a dump script to create actual dumps and compare them to
|
|
Packit |
95306a |
### the standard tzcode dump.
|
|
Packit |
95306a |
###
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my @mod; # data to store in the module
|
|
Packit |
95306a |
my %last; # LAST RULE description
|
|
Packit |
95306a |
my @mon;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if ($last) {
|
|
Packit |
95306a |
%last = _do_mods_lastrule($tzd,$zone);
|
|
Packit |
95306a |
@mon = sort keys %{ $last{"rules"} };
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
foreach my $mon (@mon) {
|
|
Packit |
95306a |
if ($mon == 1 || $mon == 12) {
|
|
Packit |
95306a |
# If a change ever happens in Jan/Dec in the LAST RULE, we
|
|
Packit |
95306a |
# may need to make sure that the year won't change (it would
|
|
Packit |
95306a |
# be horrible if it did).
|
|
Packit |
95306a |
warn "[_do_mods_tzdata] LAST RULE in Jan/Dec [$zone, $mon]\n";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my $didlast = 0;
|
|
Packit |
95306a |
my($begUT,$begLT,$endUT,$endLT,$offsetref);
|
|
Packit |
95306a |
while (@dates) {
|
|
Packit |
95306a |
($year,$begUT,$begLT,$offset,$offsetref,$abb,$isdst,$endUT,$endLT,@dates) = @dates;
|
|
Packit |
95306a |
@offset = @$offsetref;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if ($year <= $keep_year || ! $last) {
|
|
Packit |
95306a |
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# Store critical dates from dump files for years <= $keep_year
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
|
|
Packit |
95306a |
push(@mod,$year,$begUT,$begLT,$offset,$offsetref,$abb,$isdst,$endUT,$endLT);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if ($year == $keep_year && $last) {
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my $mon = shift(@mon);
|
|
Packit |
95306a |
return 1 if (! $mon);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if ($isdst != $last{"rules"}{$mon}{"isdst"}) {
|
|
Packit |
95306a |
warn "[_do_mods_tzdata] isdst mismatch in LAST RULE " .
|
|
Packit |
95306a |
"[$zone, $mon]\n";
|
|
Packit |
95306a |
return 1;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
if ($offset ne
|
|
Packit |
95306a |
$last{"zone"}{ ($isdst ? "dstoff" : "stdoff") }) {
|
|
Packit |
95306a |
warn "[_do_mods_tzdata] offset mismatch in LAST RULE " .
|
|
Packit |
95306a |
"[$zone, $mon]\n";
|
|
Packit |
95306a |
return 1;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$last{"rules"}{$mon}{"abb"} = $abb;
|
|
Packit |
95306a |
_do_mods_years($abbrev,$zone,$abb,$keep_year+1,9999)
|
|
Packit |
95306a |
if ($abb !~ /^[+-]?\d*$/);
|
|
Packit |
95306a |
$didlast++;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if ($last && $didlast != 2) {
|
|
Packit |
95306a |
warn "[_do_mods_tzdata] LAST RULE incomplete [$zone]\n";
|
|
Packit |
95306a |
return 1;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_do_mods_write($zone,$module,[@mod],%last);
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# This returns a hash of information concerning "last rules". This
|
|
Packit |
95306a |
# information will allow us to calculate critical dates in future
|
|
Packit |
95306a |
# years.
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# Information consists of:
|
|
Packit |
95306a |
# flag,dow,num : See TZdata.pm (used to calculate a DoM)
|
|
Packit |
95306a |
# add : Some of the DoM calculations do not
|
|
Packit |
95306a |
# return the final DoM after offsets have
|
|
Packit |
95306a |
# been applied. If this is +1, it'll add
|
|
Packit |
95306a |
# a day. If it's -1, it'll subtract a day.
|
|
Packit |
95306a |
# time,abb,offset : Information that should be constant.
|
|
Packit |
95306a |
# dst : Whether it is a change to DST or not.
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
sub _do_mods_lastrule {
|
|
Packit |
95306a |
my($tzd,$zone) = @_;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Get the rule dates that apply to $keep_year
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my @rules = $tzd->_zoneInfo($zone,"rules",$keep_year);
|
|
Packit |
95306a |
my @r;
|
|
Packit |
95306a |
while (@rules) {
|
|
Packit |
95306a |
my $rule = shift(@rules);
|
|
Packit |
95306a |
my $type = shift(@rules);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# All LAST RULES are currently of type TZ_RULE . If this
|
|
Packit |
95306a |
# ever changes, we'll have to add support.
|
|
Packit |
95306a |
if ($type != $Date::Manip::TZdata::TZ_RULE) {
|
|
Packit |
95306a |
warn "[_do_mods_lastrule] unsupported rule type [$zone]\n";
|
|
Packit |
95306a |
return "";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
push(@r,$tzd->_ruleInfo($rule,"rules",$keep_year));
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Make sure that there are exactly two rules. If there are
|
|
Packit |
95306a |
# not, we'll need to add support.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if ($#r != 1) {
|
|
Packit |
95306a |
warn "[_do_mods_lastrule] two rules required [$zone]\n";
|
|
Packit |
95306a |
return "";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Also get the zone line that applies. There must be one or
|
|
Packit |
95306a |
# we'll need to add support.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my @zone = $tzd->_zoneInfo($zone,"zonelines",$keep_year);
|
|
Packit |
95306a |
if ($#zone != 0) {
|
|
Packit |
95306a |
warn "[_do_mods_lastrule] one zone line required [$zone]\n";
|
|
Packit |
95306a |
return "";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Analyze the rules/zone to get the "last rule" (i.e. information
|
|
Packit |
95306a |
# that can be used to calculate critical dates in future years).
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# Some additional information will be added once dump lines are
|
|
Packit |
95306a |
# analyzed.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my %last = ( "year" => $keep_year + 1,
|
|
Packit |
95306a |
"zone" => { "stdoff" => $dmb->_delta_convert("offset",$zone[0][0]),
|
|
Packit |
95306a |
"dstoff" => '' },
|
|
Packit |
95306a |
"rules" => {},
|
|
Packit |
95306a |
);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my $totdst = 0;
|
|
Packit |
95306a |
my $totst = 0;
|
|
Packit |
95306a |
foreach my $rule (@r) {
|
|
Packit |
95306a |
my($y0,$y1,$ytype,$mon,$flag,$dow,$num,$timetype,$time,$offset,
|
|
Packit |
95306a |
$lett) = @$rule;
|
|
Packit |
95306a |
my $isdst = ($offset eq "00:00:00" ? 0 : 1);
|
|
Packit |
95306a |
$totdst += $isdst;
|
|
Packit |
95306a |
$totst += (1-$isdst);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if ($isdst) {
|
|
Packit |
95306a |
my $dstoff = $dmb->calc_time_time( $dmb->split("time",$last{"zone"}{"stdoff"}),
|
|
Packit |
95306a |
$dmb->split("time",$offset));
|
|
Packit |
95306a |
$dstoff = $dmb->join("offset",$dstoff);
|
|
Packit |
95306a |
$last{"zone"}{"dstoff"} = $dstoff;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$mon="0$mon" if (length($mon) != 2);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$last{"rules"}{$mon} = { "flag" => $flag,
|
|
Packit |
95306a |
"dow" => $dow,
|
|
Packit |
95306a |
"num" => $num,
|
|
Packit |
95306a |
"type" => $timetype,
|
|
Packit |
95306a |
"time" => $time,
|
|
Packit |
95306a |
"isdst" => $isdst,
|
|
Packit |
95306a |
"abb" => "",
|
|
Packit |
95306a |
};
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# One rule must be standard time, one must be daylight savings time.
|
|
Packit |
95306a |
# If this is not the case, we'll have to add support.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if (exists $last_zone_offsets{$zone}) {
|
|
Packit |
95306a |
if (! $last{"zone"}{"dstoff"}) {
|
|
Packit |
95306a |
$last{"zone"}{"dstoff"} = $last{"zone"}{"stdoff"};
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my $expdst = $last_zone_offsets{$zone}{"dst"};
|
|
Packit |
95306a |
my $expst = $last_zone_offsets{$zone}{"st"};
|
|
Packit |
95306a |
if ($totdst != $expdst ||
|
|
Packit |
95306a |
$totst != $expst) {
|
|
Packit |
95306a |
warn "\n" .
|
|
Packit |
95306a |
"[_do_mods_lastrule] wrong number of DST/STD offsets\n" .
|
|
Packit |
95306a |
" [exp $expdst/$expst got $totdst/$totst] [$zone]\n";
|
|
Packit |
95306a |
return "";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
} elsif ($totdst != 1 || $totst != 1) {
|
|
Packit |
95306a |
warn "[_do_mods_lastrule] 1 DST and 1 STD rule required [$zone]\n";
|
|
Packit |
95306a |
return "";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
return %last;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Split a dump line and return the values.
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
sub _do_mods_splitdump {
|
|
Packit |
95306a |
my($line) = @_;
|
|
Packit |
95306a |
my(%mon) = qw(Jan 01 Feb 02 Mar 03 Apr 04 May 05 Jun 06
|
|
Packit |
95306a |
Jul 07 Aug 08 Sep 09 Oct 10 Nov 11 Dec 12);
|
|
Packit |
95306a |
my(%dow) = qw(Mon 1 Tue 2 Wed 3 Thu 4 Fri 5 Sat 6 Sun 7);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my($z,$dowU,$monU,$domU,$timeU,$yearU,$utc,$equal,
|
|
Packit |
95306a |
$dowW,$monW,$domW,$timeW,$yearW,$abb,$isdst) = split(/\s+/,$line);
|
|
Packit |
95306a |
$isdst =~ s/isdst=//;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$monU = $mon{$monU} if (exists $mon{$monU});
|
|
Packit |
95306a |
$monW = $mon{$monW} if (exists $mon{$monW});
|
|
Packit |
95306a |
$monU = "0$monU" if (length($monU) != 2);
|
|
Packit |
95306a |
$monW = "0$monW" if (length($monW) != 2);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$dowU = $dow{$dowU} if (exists $dow{$dowU});
|
|
Packit |
95306a |
$dowU = $dow{$dowW} if (exists $dow{$dowW});
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$domU = "0$domU" if (length($domU) != 2);
|
|
Packit |
95306a |
$domW = "0$domW" if (length($domW) != 2);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
return ($dowU,$monU,$domU,$timeU,$yearU,$dowW,$monW,$domW,$timeW,$yearW,
|
|
Packit |
95306a |
$abb,$isdst);
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# This records an element as having been used in a given year.
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
sub _do_mods_years {
|
|
Packit |
95306a |
my($hash,$zone,$ele,$year,$year2) = @_;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if (exists $$hash{$ele}{$zone}) {
|
|
Packit |
95306a |
$$hash{$ele}{$zone}[1] = $year2;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
} else {
|
|
Packit |
95306a |
$$hash{$ele}{$zone} = [$year,$year2];
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# This creates a module from an offset.
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
sub _do_mods_offset {
|
|
Packit |
95306a |
my($tzd,$abbrev,$data,$zone,$module,$offset) = @_;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my($abb) = $zone;
|
|
Packit |
95306a |
$abb =~ s/Etc\///;
|
|
Packit |
95306a |
_do_mods_years($abbrev,$zone,$abb,"0001","9999");
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$offset = $dmb->_delta_convert("offset",$offset);
|
|
Packit |
95306a |
my @offset = @{ $dmb->split("offset",$offset) };
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my @begUT = @{ $dmb->split("date",$first_date) };
|
|
Packit |
95306a |
my @begLT = @{ $dmb->calc_date_time(\@begUT,\@offset) };
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my @endUT = @{ $dmb->split("date",$last_date) };
|
|
Packit |
95306a |
my @endLT = @{ $dmb->calc_date_time(\@endUT,\@offset) };
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_do_mods_write($zone,$module,
|
|
Packit |
95306a |
["0001",[@begUT],[@begLT],$offset,[@offset],$abb,0,
|
|
Packit |
95306a |
[@endUT],[@endLT]],
|
|
Packit |
95306a |
());
|
|
Packit |
95306a |
$$data{$zone}{"0001"} = [ '', [$abb,$offset,0] ];
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
sub _do_mods_write {
|
|
Packit |
95306a |
my($zone,$module,$dates,%last) = @_;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Store the critical dates in the module
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my @tmp = `cat tzdata/_version`;
|
|
Packit |
95306a |
chomp(@tmp);
|
|
Packit |
95306a |
my $tzdata_vers = "tzdata" . $tmp[0];
|
|
Packit |
95306a |
my $tzcode_vers = "tzcode" . $tmp[1];
|
|
Packit |
95306a |
my $timestamp = `date`;
|
|
Packit |
95306a |
chomp($timestamp);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my $out = new IO::File;
|
|
Packit |
95306a |
$out->open(">$mod_dir/$module.pm");
|
|
Packit |
95306a |
print $out "package #
|
|
Packit |
95306a |
Date::Manip::TZ::$module;
|
|
Packit |
95306a |
# Copyright (c) 2008-$curr_year Sullivan Beck. All rights reserved.
|
|
Packit |
95306a |
# This program is free software; you can redistribute it and/or modify it
|
|
Packit |
95306a |
# under the same terms as Perl itself.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# This file was automatically generated. Any changes to this file will
|
|
Packit |
95306a |
# be lost the next time 'tzdata' is run.
|
|
Packit |
95306a |
# Generated on: $timestamp
|
|
Packit |
95306a |
# Data version: $tzdata_vers
|
|
Packit |
95306a |
# Code version: $tzcode_vers
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# This module contains data from the zoneinfo time zone database. The original
|
|
Packit |
95306a |
# data was obtained from the URL:
|
|
Packit |
95306a |
# ftp://$tzdata_src/$tzdata_dir
|
|
Packit |
95306a |
|
|
Packit |
95306a |
use strict;
|
|
Packit |
95306a |
use warnings;
|
|
Packit |
95306a |
require 5.010000;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
our (\%Dates,\%LastRule);
|
|
Packit |
95306a |
END {
|
|
Packit |
95306a |
undef \%Dates;
|
|
Packit |
95306a |
undef \%LastRule;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
our (\$VERSION);
|
|
Packit |
95306a |
\$VERSION='6.60';
|
|
Packit |
95306a |
END { undef \$VERSION; }
|
|
Packit |
95306a |
|
|
Packit |
95306a |
\%Dates = (
|
|
Packit |
95306a |
";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my @dates = @$dates;
|
|
Packit |
95306a |
my $lastyear = 0;
|
|
Packit |
95306a |
my ($year,$begUT,$begLT,$offset,$offsetref,$abb,$isdst,$endUT,$endLT);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
while (@dates) {
|
|
Packit |
95306a |
($year,$begUT,$begLT,$offset,$offsetref,$abb,$isdst,$endUT,$endLT,@dates) =
|
|
Packit |
95306a |
@dates;
|
|
Packit |
95306a |
$year += 0;
|
|
Packit |
95306a |
my $yrprt = $year . " "x(4-length($year));
|
|
Packit |
95306a |
if ($year != $lastyear) {
|
|
Packit |
95306a |
if ($lastyear) {
|
|
Packit |
95306a |
print $out " ],\n";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
print $out " $yrprt =>\n";
|
|
Packit |
95306a |
print $out " [\n";
|
|
Packit |
95306a |
$lastyear = $year;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
my $begUTs = $dmb->join("date",$begUT);
|
|
Packit |
95306a |
my $begLTs = $dmb->join("date",$begLT);
|
|
Packit |
95306a |
my $endUTs = $dmb->join("date",$endUT);
|
|
Packit |
95306a |
my $endLTs = $dmb->join("date",$endLT);
|
|
Packit |
95306a |
$begUT = join(",",map { $_+0 } @$begUT);
|
|
Packit |
95306a |
$begLT = join(",",map { $_+0 } @$begLT);
|
|
Packit |
95306a |
$endUT = join(",",map { $_+0 } @$endUT);
|
|
Packit |
95306a |
$endLT = join(",",map { $_+0 } @$endLT);
|
|
Packit |
95306a |
$offsetref = join(",",map { $_+0 } @$offsetref);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $out " [ [$begUT],[$begLT],'$offset',[$offsetref],\n";
|
|
Packit |
95306a |
print $out " '$abb',$isdst,[$endUT],[$endLT],\n";
|
|
Packit |
95306a |
print $out " '$begUTs','$begLTs','$endUTs','$endLTs' ],\n";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $out " ],\n";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $out ");
|
|
Packit |
95306a |
|
|
Packit |
95306a |
\%LastRule = (
|
|
Packit |
95306a |
";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if (exists $last{"year"}) {
|
|
Packit |
95306a |
print $out " 'zone' => {\n";
|
|
Packit |
95306a |
foreach my $key (sort keys %{ $last{"zone"} }) {
|
|
Packit |
95306a |
my $val = $last{"zone"}{$key};
|
|
Packit |
95306a |
print $out " "x16,"'$key' => '$val',\n";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $out " },
|
|
Packit |
95306a |
'rules' => {\n";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
foreach my $mon (sort keys %{ $last{"rules"} }) {
|
|
Packit |
95306a |
print $out " "x16,"'$mon' => {\n";
|
|
Packit |
95306a |
my $flag = $last{"rules"}{$mon}{"flag"};
|
|
Packit |
95306a |
if ($flag == $Date::Manip::TZdata::TZ_DOM) {
|
|
Packit |
95306a |
$flag = "dom";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
} elsif ($flag == $Date::Manip::TZdata::TZ_LAST) {
|
|
Packit |
95306a |
$flag = "last";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
} elsif ($flag == $Date::Manip::TZdata::TZ_GE) {
|
|
Packit |
95306a |
$flag = "ge";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
} elsif ($flag == $Date::Manip::TZdata::TZ_LE) {
|
|
Packit |
95306a |
$flag = "le";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
$last{"rules"}{$mon}{"flag"} = $flag;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
foreach my $key (qw(flag dow num type time isdst abb)) {
|
|
Packit |
95306a |
print $out " "x25,"'$key'", " "x(7-length($key))," => '",
|
|
Packit |
95306a |
$last{"rules"}{$mon}{$key},"',\n";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
print $out " "x24,"},\n";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $out " },\n";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $out ");
|
|
Packit |
95306a |
|
|
Packit |
95306a |
1;
|
|
Packit |
95306a |
";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$out->close;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
############################################################################
|
|
Packit |
95306a |
# DO_OFF
|
|
Packit |
95306a |
############################################################################
|
|
Packit |
95306a |
|
|
Packit |
95306a |
sub do_off {
|
|
Packit |
95306a |
print "Offset modules...\n";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my $data = _yaml_read("tzdata/_data");
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Get a list of all zones which an offset appears in, and the year
|
|
Packit |
95306a |
# range of the offset.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my %offset_un = ( 0 => {}, 1 => {} );
|
|
Packit |
95306a |
|
|
Packit |
95306a |
ZONE:foreach my $zone (keys %$data) {
|
|
Packit |
95306a |
my $lastoffset = '';
|
|
Packit |
95306a |
my $lastisdst = '';
|
|
Packit |
95306a |
my @year = sort keys %{ $$data{$zone} };
|
|
Packit |
95306a |
while (@year) {
|
|
Packit |
95306a |
my $year = shift(@year);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# The offset at the end of the previous year is still in
|
|
Packit |
95306a |
# affect.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if ($lastoffset) {
|
|
Packit |
95306a |
_do_mods_years($offset_un{$lastisdst},$zone,$lastoffset,$year,$year);
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my ($type,@tmp) = @{ $$data{$zone}{$year} };
|
|
Packit |
95306a |
|
|
Packit |
95306a |
foreach my $tmp (@tmp) {
|
|
Packit |
95306a |
my($abb,$offset,$isdst) = @$tmp;
|
|
Packit |
95306a |
$lastoffset = $offset;
|
|
Packit |
95306a |
$lastisdst = $isdst;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if ($type =~ /last/) {
|
|
Packit |
95306a |
_do_mods_years($offset_un{$isdst},$zone,$offset,$year,9999);
|
|
Packit |
95306a |
} else {
|
|
Packit |
95306a |
_do_mods_years($offset_un{$isdst},$zone,$offset,$year,$year);
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
next ZONE if ($type =~ /last/);
|
|
Packit |
95306a |
_do_mods_years($offset_un{$lastisdst},$zone,$lastoffset,$year,9999)
|
|
Packit |
95306a |
if (! @year);
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Convert %offset to a couple other formats that will be useful.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my %offset_or;
|
|
Packit |
95306a |
$offset_or{0} = _order_elements($offset_un{0});
|
|
Packit |
95306a |
$offset_or{1} = _order_elements($offset_un{1});
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my %offset2_or;
|
|
Packit |
95306a |
foreach my $isdst (keys %offset_un) {
|
|
Packit |
95306a |
foreach my $offset (keys %{ $offset_un{$isdst} }) {
|
|
Packit |
95306a |
$offset2_or{$offset}{$isdst} = $offset_or{$isdst}{$offset};
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Come up with a module name for each offset.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my %offmod;
|
|
Packit |
95306a |
my $o = "000";
|
|
Packit |
95306a |
foreach my $offset (sort keys %offset2_or) {
|
|
Packit |
95306a |
my $offmod = "off$o";
|
|
Packit |
95306a |
$offmod{$offset} = $offmod;
|
|
Packit |
95306a |
$o++;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Write out each module
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my $num = keys %offmod;
|
|
Packit |
95306a |
my $len = length($num);
|
|
Packit |
95306a |
my $i = 0;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print " module "," "x($len-length($i)),"$i / $num";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_warn_changes($offset_or{0},$def_off{0},15,12,33,"0");
|
|
Packit |
95306a |
_warn_changes($offset_or{1},$def_off{1},15,12,33,"1");
|
|
Packit |
95306a |
|
|
Packit |
95306a |
system("rm -f $off_dir/*");
|
|
Packit |
95306a |
foreach my $offset (sort keys %offset2_or) {
|
|
Packit |
95306a |
$i++;
|
|
Packit |
95306a |
print "\010"x($len*2+3)," "x($len-length($i)),"$i / $num";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my $offmod = $offmod{$offset};
|
|
Packit |
95306a |
_do_off($offset,$offmod,\%offset_or);
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
print "\n";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_yaml_write(\%offmod,"tzdata/_offmod",0);
|
|
Packit |
95306a |
_yaml_write(\%offset_un,"tzdata/_offset_un",0);
|
|
Packit |
95306a |
_yaml_write(\%offset_or,"tzdata/_offset_or",0);
|
|
Packit |
95306a |
_yaml_write(\%offset2_or,"tzdata/_offset2_or",0);
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
sub _do_off {
|
|
Packit |
95306a |
my($offset,$module,$offset_or) = @_;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my @tmp = `cat tzdata/_version`;
|
|
Packit |
95306a |
chomp(@tmp);
|
|
Packit |
95306a |
my $tzdata_vers = "tzdata" . $tmp[0];
|
|
Packit |
95306a |
my $tzcode_vers = "tzcode" . $tmp[1];
|
|
Packit |
95306a |
my $timestamp = `date`;
|
|
Packit |
95306a |
chomp($timestamp);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my $out = new IO::File;
|
|
Packit |
95306a |
my $mod = "Date::Manip::Offset::$module";
|
|
Packit |
95306a |
$out->open(">$off_dir/$module.pm");
|
|
Packit |
95306a |
print $out "package #
|
|
Packit |
95306a |
Date::Manip::Offset::$module;
|
|
Packit |
95306a |
# Copyright (c) 2008-$curr_year Sullivan Beck. All rights reserved.
|
|
Packit |
95306a |
# This program is free software; you can redistribute it and/or modify it
|
|
Packit |
95306a |
# under the same terms as Perl itself.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# This file was automatically generated. Any changes to this file will
|
|
Packit |
95306a |
# be lost the next time 'tzdata' is run.
|
|
Packit |
95306a |
# Generated on: $timestamp
|
|
Packit |
95306a |
# Data version: $tzdata_vers
|
|
Packit |
95306a |
# Code version: $tzcode_vers
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# This module contains data from the zoneinfo time zone database. The original
|
|
Packit |
95306a |
# data was obtained from the URL:
|
|
Packit |
95306a |
# ftp://$tzdata_src/$tzdata_dir
|
|
Packit |
95306a |
|
|
Packit |
95306a |
use strict;
|
|
Packit |
95306a |
use warnings;
|
|
Packit |
95306a |
require 5.010000;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
our (\$VERSION);
|
|
Packit |
95306a |
\$VERSION='6.60';
|
|
Packit |
95306a |
END { undef \$VERSION; }
|
|
Packit |
95306a |
|
|
Packit |
95306a |
our (\$Offset,\%Offset);
|
|
Packit |
95306a |
END {
|
|
Packit |
95306a |
undef \$Offset;
|
|
Packit |
95306a |
undef \%Offset;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
\$Offset = '$offset';
|
|
Packit |
95306a |
|
|
Packit |
95306a |
\%Offset = (
|
|
Packit |
95306a |
";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
foreach my $isdst (sort keys %$offset_or) {
|
|
Packit |
95306a |
next if (! exists $$offset_or{$isdst}{$offset});
|
|
Packit |
95306a |
my @tmp = @{ $$offset_or{$isdst}{$offset} };
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $out " "x3,$isdst," => [\n";
|
|
Packit |
95306a |
while (@tmp) {
|
|
Packit |
95306a |
my $zone = shift(@tmp);
|
|
Packit |
95306a |
my $year1 = shift(@tmp);
|
|
Packit |
95306a |
my $year2 = shift(@tmp);
|
|
Packit |
95306a |
$zone = lc($zone);
|
|
Packit |
95306a |
print $out " "x6,"'$zone',\n";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
print $out " "x6,"],\n";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $out ");
|
|
Packit |
95306a |
|
|
Packit |
95306a |
1;
|
|
Packit |
95306a |
";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$out->close;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
############################################################################
|
|
Packit |
95306a |
# DO_ZONES
|
|
Packit |
95306a |
############################################################################
|
|
Packit |
95306a |
|
|
Packit |
95306a |
sub do_zones {
|
|
Packit |
95306a |
print "Zones module...\n";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my @tmp = `cat tzdata/_version`;
|
|
Packit |
95306a |
chomp(@tmp);
|
|
Packit |
95306a |
my $tzdata_vers = "tzdata" . $tmp[0];
|
|
Packit |
95306a |
my $tzcode_vers = "tzcode" . $tmp[1];
|
|
Packit |
95306a |
my $timestamp = `date`;
|
|
Packit |
95306a |
chomp($timestamp);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my $zone_list = _yaml_read("tzdata/_zone_list");
|
|
Packit |
95306a |
my $alias_list = _yaml_read("tzdata/_alias_list");
|
|
Packit |
95306a |
my $offset2_or = _yaml_read("tzdata/_offset2_or");
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my $out = new IO::File;
|
|
Packit |
95306a |
$out->open(">$zones_pm");
|
|
Packit |
95306a |
my $pod = new IO::File;
|
|
Packit |
95306a |
$pod->open(">$zones_pod");
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $out "package Date::Manip::Zones;
|
|
Packit |
95306a |
# Copyright (c) 2008-$curr_year Sullivan Beck. All rights reserved.
|
|
Packit |
95306a |
# This program is free software; you can redistribute it and/or modify it
|
|
Packit |
95306a |
# under the same terms as Perl itself.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# This file was automatically generated. Any changes to this file will
|
|
Packit |
95306a |
# be lost the next time 'tzdata' is run.
|
|
Packit |
95306a |
# Generated on: $timestamp
|
|
Packit |
95306a |
# Data version: $tzdata_vers
|
|
Packit |
95306a |
# Code version: $tzcode_vers
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# This module contains data from the zoneinfo time zone database. The original
|
|
Packit |
95306a |
# data was obtained from the URL:
|
|
Packit |
95306a |
# ftp://$tzdata_src/$tzdata_dir
|
|
Packit |
95306a |
|
|
Packit |
95306a |
use strict;
|
|
Packit |
95306a |
use warnings;
|
|
Packit |
95306a |
require 5.010000;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
our (\$VERSION);
|
|
Packit |
95306a |
\$VERSION='6.60';
|
|
Packit |
95306a |
END { undef \$VERSION; }
|
|
Packit |
95306a |
|
|
Packit |
95306a |
our (\$TzdataVersion,\$TzcodeVersion,
|
|
Packit |
95306a |
\$FirstDate,\$LastDate,\$LastYear,
|
|
Packit |
95306a |
\%Module,\%ZoneNames,\%Alias,\%Abbrev,\%Offmod);
|
|
Packit |
95306a |
END {
|
|
Packit |
95306a |
undef \$TzdataVersion;
|
|
Packit |
95306a |
undef \$TzcodeVersion;
|
|
Packit |
95306a |
undef \$FirstDate;
|
|
Packit |
95306a |
undef \$LastDate;
|
|
Packit |
95306a |
undef \$LastYear;
|
|
Packit |
95306a |
undef \%Module;
|
|
Packit |
95306a |
undef \%ZoneNames;
|
|
Packit |
95306a |
undef \%Alias;
|
|
Packit |
95306a |
undef \%Abbrev;
|
|
Packit |
95306a |
undef \%Offmod;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
\$TzdataVersion = '$tzdata_vers';
|
|
Packit |
95306a |
\$TzcodeVersion = '$tzcode_vers';
|
|
Packit |
95306a |
\$FirstDate = '$first_date';
|
|
Packit |
95306a |
\$LastDate = '$last_date';
|
|
Packit |
95306a |
\$LastYear = '$keep_year';
|
|
Packit |
95306a |
|
|
Packit |
95306a |
";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $pod "
|
|
Packit |
95306a |
# Copyright (c) 2008-$curr_year Sullivan Beck. All rights reserved.
|
|
Packit |
95306a |
# This program is free software; you can redistribute it and/or modify it
|
|
Packit |
95306a |
# under the same terms as Perl itself.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# This file was automatically generated. Any changes to this file will
|
|
Packit |
95306a |
# be lost the next time 'tzdata' is run.
|
|
Packit |
95306a |
# Generated on: $timestamp
|
|
Packit |
95306a |
# Data version: $tzdata_vers
|
|
Packit |
95306a |
# Code version: $tzcode_vers
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# This module contains data from the zoneinfo time zone database. The original
|
|
Packit |
95306a |
# data was obtained from the URL:
|
|
Packit |
95306a |
# ftp://$tzdata_src/$tzdata_dir
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$podstr
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$hdstr NAME
|
|
Packit |
95306a |
|
|
Packit |
95306a |
Date::Manip::Zones - Time zone information
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$hdstr DESCRIPTION
|
|
Packit |
95306a |
|
|
Packit |
95306a |
This module is automatically generated. It contains a complete list of
|
|
Packit |
95306a |
time zones specified in the standard zoneinfo (or Olson) databases
|
|
Packit |
95306a |
obtained from:
|
|
Packit |
95306a |
|
|
Packit |
95306a |
L<ftp://$tzdata_src/$tzdata_dir/tzdata_vers.tar.gz>
|
|
Packit |
95306a |
|
|
Packit |
95306a |
All information is stored in variables, so this module provide no
|
|
Packit |
95306a |
routines for dealing with time zone information. For routines related
|
|
Packit |
95306a |
to time zones, see the documentation for the L<Date::Manip::TZ> module.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_do_zones_zones($out,$pod,$zone_list);
|
|
Packit |
95306a |
_do_zones_names($out,$zone_list);
|
|
Packit |
95306a |
_do_zones_aliases($out,$pod,$zone_list,$alias_list);
|
|
Packit |
95306a |
_do_zones_defaults($out,$pod,$offset2_or);
|
|
Packit |
95306a |
_do_zones_abbrevs($out,$pod);
|
|
Packit |
95306a |
_do_zones_offsets($out,$pod);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $out "
|
|
Packit |
95306a |
1;
|
|
Packit |
95306a |
";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$out->close;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $pod "
|
|
Packit |
95306a |
$hdstr KNOWN BUGS
|
|
Packit |
95306a |
|
|
Packit |
95306a |
None known.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$hdstr BUGS AND QUESTIONS
|
|
Packit |
95306a |
|
|
Packit |
95306a |
Please refer to the L<Date::Manip::Problems> documentation for
|
|
Packit |
95306a |
information on submitting bug reports or questions to the author.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$hdstr SEE ALSO
|
|
Packit |
95306a |
|
|
Packit |
95306a |
L<Date::Manip> - main module documentation
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$hdstr LICENSE
|
|
Packit |
95306a |
|
|
Packit |
95306a |
This script is free software; you can redistribute it and/or
|
|
Packit |
95306a |
modify it under the same terms as Perl itself.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$hdstr AUTHOR
|
|
Packit |
95306a |
|
|
Packit |
95306a |
Sullivan Beck (sbeck\@cpan.org)
|
|
Packit |
95306a |
|
|
Packit |
95306a |
=cut
|
|
Packit |
95306a |
";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
sub _do_zones_zones {
|
|
Packit |
95306a |
my($out,$pod,$zone_list) = @_;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $out "
|
|
Packit |
95306a |
\%Module = (
|
|
Packit |
95306a |
";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $pod "
|
|
Packit |
95306a |
$hdstr TIME ZONES
|
|
Packit |
95306a |
|
|
Packit |
95306a |
A description for each time zone from the zoneinfo database is stored
|
|
Packit |
95306a |
in a separate module. These modules will be loaded automatically as
|
|
Packit |
95306a |
needed, and are documented here for the sake of completeness.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
The modules are available as:
|
|
Packit |
95306a |
|
|
Packit |
95306a |
Date::Manip::TZ::_MODULE_
|
|
Packit |
95306a |
|
|
Packit |
95306a |
where _MODULE_ is the name of the module for that specific time zone.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
The following time zones are derived from the standard zoneinfo
|
|
Packit |
95306a |
database:
|
|
Packit |
95306a |
|
|
Packit |
95306a |
";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_print_pod_row($pod,1, 5,'TIME ZONE',35, 2,'MODULE NAME',20);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
foreach my $zone (sort keys %$zone_list) {
|
|
Packit |
95306a |
my($mod,$type) = @{ $$zone_list{$zone} };
|
|
Packit |
95306a |
next if ($type ne "tzdata");
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_print_pod_row($pod,0, 5,$zone,35, 2,$mod,0);
|
|
Packit |
95306a |
_print_mod_row($out, 2,$zone,35,'hashkey', 2,$mod,0,'hashval');
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $pod "
|
|
Packit |
95306a |
The following time zones are NOT derived from the standard zoneinfo
|
|
Packit |
95306a |
database. They are derived from other standard sources (including
|
|
Packit |
95306a |
RFC 822):
|
|
Packit |
95306a |
|
|
Packit |
95306a |
";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_print_pod_row($pod,1, 5,'TIME ZONE',35, 2,'MODULE NAME',20);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
foreach my $zone (sort keys %$zone_list) {
|
|
Packit |
95306a |
my($mod,$type) = @{ $$zone_list{$zone} };
|
|
Packit |
95306a |
next if ($type eq "tzdata");
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_print_pod_row($pod,0, 5,$zone,35, 2,$mod,0);
|
|
Packit |
95306a |
_print_mod_row($out, 2,$zone,35,'hashkey', 2,$mod,0,'hashval');
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $out ");
|
|
Packit |
95306a |
";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
sub _do_zones_names {
|
|
Packit |
95306a |
my($out,$zone_list) = @_;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $out "
|
|
Packit |
95306a |
\%ZoneNames = (
|
|
Packit |
95306a |
";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
foreach my $zone (sort keys %$zone_list) {
|
|
Packit |
95306a |
my($mod,$type) = @{ $$zone_list{$zone} };
|
|
Packit |
95306a |
next if ($type ne "tzdata");
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_print_mod_row($out, 2,$zone,35,'hashkey', 2,$zone,0,'hashval,nocase');
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
foreach my $zone (sort keys %$zone_list) {
|
|
Packit |
95306a |
my($mod,$type) = @{ $$zone_list{$zone} };
|
|
Packit |
95306a |
next if ($type eq "tzdata");
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_print_mod_row($out, 2,$zone,35,'hashkey', 2,$zone,0,'hashval,nocase');
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $out ");
|
|
Packit |
95306a |
";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
sub _do_zones_aliases {
|
|
Packit |
95306a |
my($out,$pod,$zone_list,$alias_list) = @_;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my $tzd = Date::Manip::TZdata->new();
|
|
Packit |
95306a |
my %tzdalias = %{ $$tzd{"alias"} };
|
|
Packit |
95306a |
my $alias2_un = _yaml_read("tzdata/_alias2_un");
|
|
Packit |
95306a |
my $alias2_or = _yaml_read("tzdata/_alias2_or");
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $out "
|
|
Packit |
95306a |
\%Alias = (
|
|
Packit |
95306a |
";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Print out the standard 'zone => zone' aliases
|
|
Packit |
95306a |
|
|
Packit |
95306a |
foreach my $zone (sort keys %$zone_list) {
|
|
Packit |
95306a |
_print_mod_row($out, 2,$zone,35,'hashkey', 2,$zone,0,'hashval');
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Print out alternate time zone names from tzdata files
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $pod "
|
|
Packit |
95306a |
$hdstr TIME ZONE NAMES, ALIASES, AND ABBREVIATIONS
|
|
Packit |
95306a |
|
|
Packit |
95306a |
Time zones may be referred to as their full name
|
|
Packit |
95306a |
(e.g. America/New_York), but there are also a number of standard
|
|
Packit |
95306a |
aliases and abbreviations that may be used.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
Standard aliases are listed below. Additional aliases can be created,
|
|
Packit |
95306a |
or existing aliases overridden using the C<new_alias> method of the
|
|
Packit |
95306a |
L<Date::Manip::TZ> module.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
The zoneinfo database provides several standard aliases, including:
|
|
Packit |
95306a |
|
|
Packit |
95306a |
";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_print_pod_row($pod,1, 5,'ALTERNATE NAME',35, 2,'TIME ZONE',20);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
foreach my $alias (sort keys %tzdalias) {
|
|
Packit |
95306a |
my $zone = $tzdalias{$alias};
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Don't duplicate the 'zone => zone' or 'EST5EDT => zone' aliases
|
|
Packit |
95306a |
next if (exists $$zone_list{$zone} && $alias eq $zone);
|
|
Packit |
95306a |
next if (exists $$alias_list{$zone} && $$alias_list{$zone}[1] ne "tzdata");
|
|
Packit |
95306a |
next if (exists $$alias2_un{$zone});
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_print_pod_row($pod,0, 5,$alias,35, 2,$zone,0);
|
|
Packit |
95306a |
_print_mod_row($out, 2,$alias,35,'hashkey', 2,$zone,0,'hashval');
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Do the EST5EDT style aliases
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $pod "
|
|
Packit |
95306a |
There are a large number of possible time zone aliases of the form
|
|
Packit |
95306a |
EST5EDT. The main 4 used in the United States are CST6CDT, EST5EDT,
|
|
Packit |
95306a |
MST7MDT, and PST8PDT and these are specifically called for in RFC 822,
|
|
Packit |
95306a |
so whenever possible, these will refer to the US time zones, but some
|
|
Packit |
95306a |
aliases may possibly refer to more than one time zone. In these
|
|
Packit |
95306a |
instances, I have selected one of them to be the default time zone to
|
|
Packit |
95306a |
use (based on how recently it was used, and for what period of
|
|
Packit |
95306a |
time). In the list below, all possible time zones are listed for each
|
|
Packit |
95306a |
alias. The first time zone listed is the one used by default. The
|
|
Packit |
95306a |
default alias can be overridden as described above.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_print_pod_row($pod,1, 5,'ALTERNATE NAME',35, 2,'TIME ZONE',20);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_warn_changes($alias2_or,\%def_alias2,3,16,42);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
foreach my $ele (sort keys %$alias2_or) {
|
|
Packit |
95306a |
my @tmp = @{ $$alias2_or{$ele} };
|
|
Packit |
95306a |
my $first = $ele;
|
|
Packit |
95306a |
while (@tmp) {
|
|
Packit |
95306a |
my $alias = shift(@tmp);
|
|
Packit |
95306a |
my $year1 = shift(@tmp);
|
|
Packit |
95306a |
my $year2 = shift(@tmp);
|
|
Packit |
95306a |
_print_pod_row($pod,0, 5,$first,35, 2,$alias,0);
|
|
Packit |
95306a |
_print_mod_row($out, 2,$first,35,'hashkey', 2,$alias,0,'hashval') if ($first);
|
|
Packit |
95306a |
$first = '';
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Print out alternate time zone names other sources
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $pod "
|
|
Packit |
95306a |
There are also a number of standard aliases. Some of these are
|
|
Packit |
95306a |
included to fix minor issues with the tzdata files. Others come from
|
|
Packit |
95306a |
standard sources including RFC 822 or the list of time zone names used
|
|
Packit |
95306a |
on Microsoft Windows operating systems.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
Aliases include:
|
|
Packit |
95306a |
|
|
Packit |
95306a |
";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_print_pod_row($pod,1, 5,'ALTERNATE NAME',35, 2,'TIME ZONE',20);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
foreach my $alias (sort keys %$alias_list) {
|
|
Packit |
95306a |
my($zone,$type) = @{ $$alias_list{$alias} };
|
|
Packit |
95306a |
next if ($type eq "tzdata" || $type eq "ignore");
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Don't duplicate the 'zone => zone' aliases
|
|
Packit |
95306a |
next if (exists $$zone_list{$zone} && $alias eq $zone);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_print_pod_row($pod,0, 5,$alias,35, 2,$zone,0);
|
|
Packit |
95306a |
_print_mod_row($out, 2,$alias,35,'hashkey', 2,$zone,0,'hashval');
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $out ");
|
|
Packit |
95306a |
";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
sub _do_zones_defaults {
|
|
Packit |
95306a |
my($out,$pod,$offset2_or) = @_;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Start the defaults (POD only)
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $pod "
|
|
Packit |
95306a |
Periodically, we need to be able to determine a time zone based on an
|
|
Packit |
95306a |
offset. In addition, the ISDST may be known, and a date/time may be
|
|
Packit |
95306a |
available. The following table shows what time zones are examined based
|
|
Packit |
95306a |
on the offset, and in what order. The first match is used. If the
|
|
Packit |
95306a |
ISDST time is not known, the standard zones will be tested followed by
|
|
Packit |
95306a |
the DST zones.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
The default order can be overridden with the C<off_zones> method in the
|
|
Packit |
95306a |
L<Date::Manip::TZ> module.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_print_pod_row($pod,1, 5,'ISDST',5, 2,'OFFSET',10, 2,'TIME ZONE',25);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
foreach my $isdst (0,1) {
|
|
Packit |
95306a |
|
|
Packit |
95306a |
foreach my $off (sort { _cmp_zoneoffsets($a,$b) } keys %$offset2_or) {
|
|
Packit |
95306a |
next unless (exists $$offset2_or{$off}{$isdst});
|
|
Packit |
95306a |
my @tmp = @{ $$offset2_or{$off}{$isdst} };
|
|
Packit |
95306a |
my $zone = shift(@tmp);
|
|
Packit |
95306a |
my $year1= shift(@tmp);
|
|
Packit |
95306a |
my $year2= shift(@tmp);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my $dst = $isdst;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_print_pod_row($pod,0, 5,$dst,5, 2,$off,10, 2,$zone,0);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$off = "";
|
|
Packit |
95306a |
$dst = " ";
|
|
Packit |
95306a |
while (@tmp) {
|
|
Packit |
95306a |
$zone = shift(@tmp);
|
|
Packit |
95306a |
$year1 = shift(@tmp);
|
|
Packit |
95306a |
$year2 = shift(@tmp);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_print_pod_row($pod,0, 5,$dst,5, 2,$off,10, 2,$zone,0);
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
print $pod "\n";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
sub _cmp_zoneoffsets {
|
|
Packit |
95306a |
my($x,$y) = @_;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# A negative offset comes before a positive one
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if ($x =~ /^-/ && $y =~ /^\+/) {
|
|
Packit |
95306a |
return -1;
|
|
Packit |
95306a |
} elsif ($y =~ /^-/ && $x =~ /^\+/) {
|
|
Packit |
95306a |
return +1;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Netgative offsets are sorted reverse.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if ($x =~ /^-/) {
|
|
Packit |
95306a |
return ($y cmp $x);
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Positive offsets are sorted normally.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
return ($x cmp $y);
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
sub _do_zones_abbrevs {
|
|
Packit |
95306a |
my($out,$pod) = @_;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my $abbrev_or = _yaml_read("tzdata/_abbrev_or");
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Start the aliases output (both POD and module)
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $out "
|
|
Packit |
95306a |
\%Abbrev = (
|
|
Packit |
95306a |
";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Print out EST => ZONE aliases for abbreviations which only occur
|
|
Packit |
95306a |
# in a single zone.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
delete $$abbrev_or{'LMT'};
|
|
Packit |
95306a |
delete $$abbrev_or{'zzz'};
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Print out EST => ZONE aliases
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $pod "
|
|
Packit |
95306a |
In the time zone definitions, abbreviations are used to specify the
|
|
Packit |
95306a |
current time (e.g. EST in the America/New_York time zone). In some
|
|
Packit |
95306a |
cases, the abbreviation appears in only a single time zone, so for
|
|
Packit |
95306a |
these, there is no ambiguity.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
More often though, abbreviations are used in multiple time zones. When
|
|
Packit |
95306a |
a date is parsed that contains one of these abbreviations, it will try
|
|
Packit |
95306a |
to interpret the date using each of the time zones in the order listed
|
|
Packit |
95306a |
below until one is found which yields a valid date.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
The abbreviations LMT and zzz which occur in the zoneinfo databases
|
|
Packit |
95306a |
are ignored (and when parsing a date including them, the local time
|
|
Packit |
95306a |
zone will be used).
|
|
Packit |
95306a |
|
|
Packit |
95306a |
The default order can be overridden using the C<abbrev> method of the
|
|
Packit |
95306a |
L<Date::Manip::TZ> module.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
The order given here is open to discussion (and possible change) based
|
|
Packit |
95306a |
on changes to the timezone database. I will always place emphasis on a
|
|
Packit |
95306a |
time zone that used the abbreviation more recently than another time zone.
|
|
Packit |
95306a |
Within those constraints, I've tried to put the more commonly used time zone
|
|
Packit |
95306a |
at a higher priority. Since I'm not always able to decide which is the
|
|
Packit |
95306a |
most commonly used, I'm willing to entertain arguments for altering the order.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_print_pod_row($pod,1, 5,'ALIAS',15, 2,'TIME ZONE',20);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_warn_changes($abbrev_or,\%def_abbrev,3,14,44);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my (@abb) = sort keys %$abbrev_or;
|
|
Packit |
95306a |
foreach my $abb (@abb) {
|
|
Packit |
95306a |
my @tmp = @{ $$abbrev_or{$abb} };
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my $first = $abb;
|
|
Packit |
95306a |
my $opts1 = 'hashkey';
|
|
Packit |
95306a |
|
|
Packit |
95306a |
while (@tmp) {
|
|
Packit |
95306a |
my $zone = shift(@tmp);
|
|
Packit |
95306a |
shift(@tmp);
|
|
Packit |
95306a |
shift(@tmp);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_print_pod_row($pod,0, 5,$first,15, 2,$zone,0);
|
|
Packit |
95306a |
my $opts2 = 'list,hashval';
|
|
Packit |
95306a |
$opts2 .= ',firstlist' if ($first);
|
|
Packit |
95306a |
$opts2 .= ',lastlist' if (! @tmp);
|
|
Packit |
95306a |
_print_mod_row($out, 2,$first,12,$opts1, 2,$zone,0,$opts2);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$first = '';
|
|
Packit |
95306a |
$opts1 = 'hashkey,noquote';
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $out "
|
|
Packit |
95306a |
);
|
|
Packit |
95306a |
";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
sub _do_zones_offsets {
|
|
Packit |
95306a |
my($out,$pod) = @_;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my $offmod = _yaml_read("tzdata/_offmod");
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Start the offset output (in this case, no POD output since it
|
|
Packit |
95306a |
# doesn't seem usefule.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $out "
|
|
Packit |
95306a |
\%Offmod = (
|
|
Packit |
95306a |
";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
foreach my $offset (sort keys %$offmod) {
|
|
Packit |
95306a |
my $mod = $$offmod{$offset};
|
|
Packit |
95306a |
_print_mod_row($out, 2,$offset,10,'hashkey', 2,$mod,0,'hashval');
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $out "
|
|
Packit |
95306a |
);
|
|
Packit |
95306a |
";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
############################################################################
|
|
Packit |
95306a |
# PRINT OUT POD AND MODULE LINES
|
|
Packit |
95306a |
|
|
Packit |
95306a |
sub _print_pod_row {
|
|
Packit |
95306a |
my($out,$header,@cols) = @_;
|
|
Packit |
95306a |
my $under = '';
|
|
Packit |
95306a |
|
|
Packit |
95306a |
while (@cols) {
|
|
Packit |
95306a |
my $indent = shift(@cols);
|
|
Packit |
95306a |
my $val = shift(@cols);
|
|
Packit |
95306a |
my $wid = shift(@cols);
|
|
Packit |
95306a |
$wid = length($val) if (! $wid);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $out ' 'x$indent,$val,' 'x($wid-length($val));
|
|
Packit |
95306a |
$under .= ' 'x$indent . '-'x$wid;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
print $out "\n";
|
|
Packit |
95306a |
print $out "$under\n" if ($header);
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
sub _print_mod_row {
|
|
Packit |
95306a |
my($out,@cols) = @_;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
while (@cols) {
|
|
Packit |
95306a |
my $indent = shift(@cols);
|
|
Packit |
95306a |
my $val = shift(@cols);
|
|
Packit |
95306a |
my $wid = shift(@cols);
|
|
Packit |
95306a |
my $opts = shift(@cols);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$val = "'$val'" unless ($opts =~ /noquote/);
|
|
Packit |
95306a |
$val = lc($val) unless ($opts =~ /nocase/);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if ($opts =~ /hashkey/) {
|
|
Packit |
95306a |
# nothing
|
|
Packit |
95306a |
|
|
Packit |
95306a |
} elsif ($opts =~ /hashval/) {
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if ($opts =~ /firstlist/ && $opts =~ /lastlist/) {
|
|
Packit |
95306a |
$val = "=> [ $val ],";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
} elsif ($opts =~ /firstlist/) {
|
|
Packit |
95306a |
$val = "=> [ $val,";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
} elsif ($opts =~ /lastlist/) {
|
|
Packit |
95306a |
$val = " $val ],";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
} elsif ($opts =~ /list/) {
|
|
Packit |
95306a |
$val = " $val,";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
} else {
|
|
Packit |
95306a |
$val = "=> $val,";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
} else {
|
|
Packit |
95306a |
$val .= ',';
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$wid = length($val) if (! $wid);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
print $out ' 'x$indent,$val,' 'x($wid-length($val));
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
print $out "\n";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
############################################################################
|
|
Packit |
95306a |
# DEALING WITH THE ORDER OF ELEMENTS
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# This takes a hash:
|
|
Packit |
95306a |
# $in = { ELE => SUBELE => [YEAR1,YEAR2] }
|
|
Packit |
95306a |
# and returns a hash of the form:
|
|
Packit |
95306a |
# $out = { ELE => [ SUBELE, YEAR1, YEAR2,
|
|
Packit |
95306a |
# SUBELE, YEAR1, YEAR2, ... ] }
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# The order of the elements sorted based on the range.
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
sub _order_elements {
|
|
Packit |
95306a |
my($in) = @_;
|
|
Packit |
95306a |
my $out;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
foreach my $ele (keys %$in) {
|
|
Packit |
95306a |
my @in = _sort_by_years($$in{$ele});
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$$out{$ele} = [];
|
|
Packit |
95306a |
foreach my $subele (@in) {
|
|
Packit |
95306a |
my($year1,$year2) = @{ $$in{$ele}{$subele} };
|
|
Packit |
95306a |
push(@{ $$out{$ele} },($subele,$year1,$year2));
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
return $out;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# This sorts the keys of a hash of the form:
|
|
Packit |
95306a |
# $hash = { ELE => [YEAR1,YEAR2] }
|
|
Packit |
95306a |
# by years.
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# o An element that is active now always comes before one that isn't
|
|
Packit |
95306a |
# active now.
|
|
Packit |
95306a |
# i.e. [2000-2020] < [1900-2000] (now = 2010)
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# o A modern European timezone (WET, CET, EET) comes before others.
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# o An Antarctica element comes after one that is not Antarctica
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# o A military timezone (A-Z) comes after one that is not
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# o A UT/UTC/*GMT* timezone comes after one that is not
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# o An element that is active later comes before one that is active
|
|
Packit |
95306a |
# earlier.
|
|
Packit |
95306a |
# i.e. [X-1970] < [X-1960]; [X-2040] < [X-2020]
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# o An element that is active further in the past comes before one
|
|
Packit |
95306a |
# that is active later.
|
|
Packit |
95306a |
# i.e. [1930-X] < [1940-X]
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# o Alphabetize the rest.
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
sub _sort_by_years {
|
|
Packit |
95306a |
my($hash) = @_;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
return sort { __sort_by_years($$hash{$a},$$hash{$b},$a,$b) } keys %$hash;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
sub __sort_by_years {
|
|
Packit |
95306a |
my($a,$b,$namea,$nameb) = @_;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Find out which elements are currently active
|
|
Packit |
95306a |
my $curra = ($$a[0] <= $curry && $$a[1] >= $curry ? 1 : 0);
|
|
Packit |
95306a |
my $currb = ($$b[0] <= $curry && $$b[1] >= $curry ? 1 : 0);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# An element that is active now always comes before one that isn't
|
|
Packit |
95306a |
# active now.
|
|
Packit |
95306a |
if ($curra != $currb) {
|
|
Packit |
95306a |
return -1 if ($curra);
|
|
Packit |
95306a |
return 1;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# A modern European timezone (WET, CET, EET) comes before others.
|
|
Packit |
95306a |
if ($namea =~ /^(WET|CET|EET)$/) {
|
|
Packit |
95306a |
return -1;
|
|
Packit |
95306a |
} elsif ($nameb =~ /^(WET|CET|EET)$/) {
|
|
Packit |
95306a |
return 1;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# An Antarctica element comes after one that is not Antarctica
|
|
Packit |
95306a |
if ($namea =~ /Antarctica/) {
|
|
Packit |
95306a |
if ($nameb =~ /Antarctica/) {
|
|
Packit |
95306a |
return $namea cmp $nameb;
|
|
Packit |
95306a |
} else {
|
|
Packit |
95306a |
return 1;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
} elsif ($nameb =~ /Antarctica/) {
|
|
Packit |
95306a |
return -1;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# A military timezone (A-Z) comes after one that is not
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if ($namea =~ /^[A-Z]$/) {
|
|
Packit |
95306a |
if ($nameb =~ /^[A-Z]$/) {
|
|
Packit |
95306a |
return $namea cmp $nameb;
|
|
Packit |
95306a |
} else {
|
|
Packit |
95306a |
return 1;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
} elsif ($nameb =~ /^[A-Z]$/) {
|
|
Packit |
95306a |
return -1;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# A UT/UTC/*GMT* timezone comes after one that is not
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if ($namea =~ /UT/ || $namea =~ /GMT/) {
|
|
Packit |
95306a |
if ($nameb =~ /UT/ || $nameb =~ /GMT/) {
|
|
Packit |
95306a |
return $namea cmp $nameb;
|
|
Packit |
95306a |
} else {
|
|
Packit |
95306a |
return 1;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
} elsif ($nameb =~ /UT/ || $nameb =~ /GMT/) {
|
|
Packit |
95306a |
return -1;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# An element that is active later comes before one that is active
|
|
Packit |
95306a |
# earlier.
|
|
Packit |
95306a |
if ($$a[1] != $$b[1]) {
|
|
Packit |
95306a |
return -1 if ($$a[1] > $$b[1]);
|
|
Packit |
95306a |
return 1;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# An element that is active further in the past comes before one
|
|
Packit |
95306a |
# that is active later.
|
|
Packit |
95306a |
if ($$a[0] != $$b[0]) {
|
|
Packit |
95306a |
return -1 if ($$a[0] < $$b[0]);
|
|
Packit |
95306a |
return 1;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# We'll order anything else as America < Europe < Asia < other
|
|
Packit |
95306a |
my ($posa,$posb);
|
|
Packit |
95306a |
if ($namea =~ /^America/) { $posa = 1; }
|
|
Packit |
95306a |
elsif ($namea =~ /^Europe/) { $posa = 2; }
|
|
Packit |
95306a |
elsif ($namea =~ /^Asia/) { $posa = 3; }
|
|
Packit |
95306a |
else { $posa = 4; }
|
|
Packit |
95306a |
if ($nameb =~ /^America/) { $posb = 1; }
|
|
Packit |
95306a |
elsif ($nameb =~ /^Europe/) { $posb = 2; }
|
|
Packit |
95306a |
elsif ($nameb =~ /^Asia/) { $posb = 3; }
|
|
Packit |
95306a |
else { $posb = 4; }
|
|
Packit |
95306a |
return ($posa <=> $posb) if ($posa != $posb);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Alphabetize the rest
|
|
Packit |
95306a |
return $namea cmp $nameb;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# This will warn if %curr is different than %prev.
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
sub _warn_changes {
|
|
Packit |
95306a |
my($curr,$prev,$indent,$col1_len,$col2_len,$header) = @_;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my %tmp = map { $_,1 } (keys %$curr, keys %$prev);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
foreach my $ele (sort keys %tmp) {
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if (! exists $$curr{$ele}) {
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# If the element doesn't exist in the current set of
|
|
Packit |
95306a |
# elements, remove it from the previous set.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_warn_changes_ele($header,$ele,
|
|
Packit |
95306a |
undef,$$prev{$ele},$indent,$col1_len,$col2_len);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
} elsif (! exists $$prev{$ele}) {
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# If the element doesn't exist in the old set, add it.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
_warn_changes_ele($header,$ele,
|
|
Packit |
95306a |
$$curr{$ele},undef,$indent,$col1_len,$col2_len);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
} elsif (! ref($$prev{$ele})) {
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# The previous element is defined as either a scalar:
|
|
Packit |
95306a |
# PREV_FIRST
|
|
Packit |
95306a |
# The current first element must be the same.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if ($$curr{$ele}[0] ne $$prev{$ele}) {
|
|
Packit |
95306a |
_warn_changes_ele($header,$ele,
|
|
Packit |
95306a |
$$curr{$ele},$$prev{$ele},
|
|
Packit |
95306a |
$indent,$col1_len,$col2_len);
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
} else {
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# The previous element may be defined as a listref:
|
|
Packit |
95306a |
# [ OVERRIDE, PREV_FIRST ]
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# This will warn if the current first element is not the
|
|
Packit |
95306a |
# same as PREV_FIRST.
|
|
Packit |
95306a |
#
|
|
Packit |
95306a |
# In the second case, it will also complain if OVERRIDE is not
|
|
Packit |
95306a |
# in the list. Finally, it will reorder the list to move OVERRIDE
|
|
Packit |
95306a |
# to the start of the list.
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if ($$prev{$ele}[1] ne $$curr{$ele}[0]) {
|
|
Packit |
95306a |
_warn_changes_ele($header,$ele,
|
|
Packit |
95306a |
$$curr{$ele},$$prev{$ele},
|
|
Packit |
95306a |
$indent,$col1_len,$col2_len);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
} else {
|
|
Packit |
95306a |
my @old = @{ $$curr{$ele} };
|
|
Packit |
95306a |
my @new;
|
|
Packit |
95306a |
my $found = 0;
|
|
Packit |
95306a |
while (@old) {
|
|
Packit |
95306a |
my $tz = shift(@old);
|
|
Packit |
95306a |
my $y1 = shift(@old);
|
|
Packit |
95306a |
my $y2 = shift(@old);
|
|
Packit |
95306a |
if ($tz eq $$prev{$ele}[0]) {
|
|
Packit |
95306a |
@new = ($tz,$y1,$y2,@new,@old);
|
|
Packit |
95306a |
$found = 1;
|
|
Packit |
95306a |
last;
|
|
Packit |
95306a |
} else {
|
|
Packit |
95306a |
push(@new,$tz,$y1,$y2);
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
if ($found) {
|
|
Packit |
95306a |
$$curr{$ele} = [@new];
|
|
Packit |
95306a |
} else {
|
|
Packit |
95306a |
_warn_changes_ele($header,$ele,
|
|
Packit |
95306a |
$$curr{$ele},$$prev{$ele}[1],
|
|
Packit |
95306a |
$indent,$col1_len,$col2_len);
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
sub _warn_changes_ele {
|
|
Packit |
95306a |
my($header,$ele,$curr,$prev,$indent,$col1_len,$col2_len) = @_;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
my $val;
|
|
Packit |
95306a |
if (! defined($curr)) {
|
|
Packit |
95306a |
warn "*** REMOVE ***\n";
|
|
Packit |
95306a |
if (ref($prev)) {
|
|
Packit |
95306a |
$val = "[ $$prev[0], $$prev[1] ]";
|
|
Packit |
95306a |
} else {
|
|
Packit |
95306a |
$val = $prev;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
} elsif (! defined($prev)) {
|
|
Packit |
95306a |
warn "*** NEW ELEMENT ***\n";
|
|
Packit |
95306a |
$val = $$curr[0];
|
|
Packit |
95306a |
} else {
|
|
Packit |
95306a |
warn "*** CHANGE ELEMENT ***\n";
|
|
Packit |
95306a |
if (ref($prev)) {
|
|
Packit |
95306a |
$val = "[ $$prev[0] => $$curr[0] ]";
|
|
Packit |
95306a |
} else {
|
|
Packit |
95306a |
$val = $$curr[0];
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
warn "$header\n" if (defined $header);
|
|
Packit |
95306a |
|
|
Packit |
95306a |
$ele = "'$ele'";
|
|
Packit |
95306a |
warn " "x$indent, $ele," "x($col1_len-length($ele)),"=> '$val'\n";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
if (defined($curr)) {
|
|
Packit |
95306a |
my @tmp = @$curr;
|
|
Packit |
95306a |
while (@tmp) {
|
|
Packit |
95306a |
my $subele = shift(@tmp);
|
|
Packit |
95306a |
my $year1 = shift(@tmp);
|
|
Packit |
95306a |
my $year2 = shift(@tmp);
|
|
Packit |
95306a |
my($col2) = "'$subele'";
|
|
Packit |
95306a |
my($col3) = ",$year1,$year2,";
|
|
Packit |
95306a |
|
|
Packit |
95306a |
warn "#"," "x($indent + $col1_len + 3), $col2,
|
|
Packit |
95306a |
" "x($col2_len-length($col2)),"$col3\n";
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
############################################################################
|
|
Packit |
95306a |
# DO_CLEAN
|
|
Packit |
95306a |
############################################################################
|
|
Packit |
95306a |
|
|
Packit |
95306a |
sub do_clean {
|
|
Packit |
95306a |
print "Cleaning...\n";
|
|
Packit |
95306a |
system("rm -rf tzdata* tzcode*");
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
############################################################################
|
|
Packit |
95306a |
|
|
Packit |
95306a |
sub _yaml_read {
|
|
Packit |
95306a |
my($file) = @_;
|
|
Packit |
95306a |
return {} if (! -e $file);
|
|
Packit |
95306a |
my($data) = YAML::LoadFile($file);
|
|
Packit |
95306a |
return {} if (! defined $data);
|
|
Packit |
95306a |
return $data;
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
sub _yaml_write {
|
|
Packit |
95306a |
my($data,$file,$backup) = @_;
|
|
Packit |
95306a |
|
|
Packit |
95306a |
rename($file,"$file.bak") if ($backup && -e $file);
|
|
Packit |
95306a |
YAML::DumpFile($file,$data);
|
|
Packit |
95306a |
}
|
|
Packit |
95306a |
|
|
Packit |
95306a |
# Local Variables:
|
|
Packit |
95306a |
# mode: cperl
|
|
Packit |
95306a |
# indent-tabs-mode: nil
|
|
Packit |
95306a |
# cperl-indent-level: 3
|
|
Packit |
95306a |
# cperl-continued-statement-offset: 2
|
|
Packit |
95306a |
# cperl-continued-brace-offset: 0
|
|
Packit |
95306a |
# cperl-brace-offset: 0
|
|
Packit |
95306a |
# cperl-brace-imaginary-offset: 0
|
|
Packit |
95306a |
# cperl-label-offset: 0
|
|
Packit |
95306a |
# End:
|