The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Date::Manip::TZ::$module - Support for the $zone time zone

SYNPOSIS

This module contains data from the Olsen database for the time zone. It is not intended to be used directly (other Date::Manip modules will load it as needed).

NAME

Date::Manip::Offset::$module - Support for the $offset offset

SYNPOSIS

This module contains data from the Olsen database for the offset. It is not intended to be used directly (other Date::Manip modules will load it as needed).

NAME

Date::Manip::Zones - Time zone information

DESCRIPTION

This module is automatically generated. It contains a complete list of time zones specified in the standard zoneinfo (or Olson) databases obtained from:

   ftp://$tzdata_src$tzdata_dir

All information is stored in variables, so this module provide no routines for dealing with time zone information. For routines related to time zones, see the documentation for the Date::Manip::TZ module.

";

   _do_zones_zones($out,$pod,$module);
   _do_zones_names($out,$module);
   _do_zones_aliases($out,$pod,$module,$alias);
   _do_zones_defaults($out,$pod,$data2);
   _do_zones_abbrevs($out,$pod);
   _do_zones_offsets($out,$pod);

   print $out "
1;
";

   $out->close;

   print $pod "
=head1 KNOWN BUGS

None known.

BUGS AND QUESTIONS

Please refer to the Date::Manip::Problems documentation for information on submitting bug reports or questions to the author.

SEE ALSO

Date::Manip - main module documentation

LICENSE

This script is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

AUTHOR

Sullivan Beck (sbeck\@cpan.org)

TIME ZONES

A description for each time zone from the zoneinfo database is stored in a separate module. These modules will be loaded automatically as needed, and are documented here for the sake of completeness.

The modules are available as:

   Date::Manip::TZ::_MODULE_

where _MODULE_ is the name of the module for that specific time zone.

The following time zones are derived from the standard zoneinfo database:

"; my($zone,$mod) = ("TIME ZONE","MODULE NAME"); print $pod " "x5,$zone," "x(35-length($zone))," $mod\n"; print $pod " "x5,"-"x35," ","-"x11,"\n";

   foreach my $zone (sort keys %$module) {
      my($mod,$type) = @{ $$module{$zone} };
      next  if ($type ne "tzdata");

      print $pod " "x5,$zone," "x(35-length($zone)),"  $mod\n";
      $zone = lc($zone);
      print $out "  '$zone'" . " "x(25-length($zone)) . "=> '$mod',\n";
   }

   print $pod "
The following time zones are NOT derived from the standard zoneinfo
database. They are derived from other standard sources (including
RFC 822):

";

   ($zone,$mod) = ("TIME ZONE","MODULE NAME");
   print $pod " "x5,$zone," "x(35-length($zone)),"  $mod\n";
   print $pod " "x5,"-"x35,"  ","-"x11,"\n";

   foreach my $zone (sort keys %$module) {
      my($mod,$type) = @{ $$module{$zone} };
      next  if ($type eq "tzdata");

      print $pod " "x5,$zone," "x(35-length($zone)),"  $mod\n";
      $zone = lc($zone);
      print $out "  '$zone'" . " "x(25-length($zone)) . "=> '$mod',\n";
   }

   print $out ");
";
}

sub _do_zones_names { my($out,$module) = @_;

   print $out "
\%ZoneNames = (
";

   foreach my $zone (sort keys %$module) {
      my($mod,$type) = @{ $$module{$zone} };
      next  if ($type ne "tzdata");
      my $lcz = lc($zone);
      print $out "  '$lcz'" . " "x(25-length($zone)) . "=> '$zone',\n";
   }

   foreach my $zone (sort keys %$module) {
      my($mod,$type) = @{ $$module{$zone} };
      next  if ($type eq "tzdata");
      my $lcz = lc($zone);
      print $out "  '$lcz'" . " "x(25-length($zone)) . "=> '$zone',\n";
   }

   print $out ");
";
}

sub _do_zones_aliases { my($out,$pod,$module,$aliases) = @_;

   my $tzd      = Date::Manip::TZdata->new();
   my %tzdalias = %{ $$tzd{"alias"} };
   my $alias2   = _yaml_read("tzdata/_alias2");

   print $out "
\%Alias = (
";

   # Print out the standard 'zone => zone' aliases

   foreach my $zone (sort keys %$module) {
      my $alias = lc($zone);
      print $out "  '$alias'" . " "x(25-length($alias)) . "=> '$alias',\n";
   }

   # Print out alternate time zone names from tzdata files

   print $pod "
=head1 TIME ZONE NAMES, ALIASES, AND ABBREVIATIONS

Time zones may be referred to as their full name (e.g. America/New_York), but there are also a number of standard aliases and abbreviations that may be used.

Standard aliases are listed below. Additional aliases can be created, or existing aliases overridden using the new_alias method of the Date::Manip::TZ module.

The zoneinfo database provides several standard aliases, including:

";

   my ($alias,$zone) = ("ALTERNATE NAME","TIME ZONE");
   print $pod " "x5,$alias," "x(35-length($alias)),"  $zone\n";
   print $pod " "x5,"-"x35,"  ","-"x8,"\n\n";

   foreach $alias (sort keys %tzdalias) {
      $zone = $tzdalias{$alias};

      # Don't duplicate the 'zone => zone' or 'EST5EDT => zone' aliases
      next  if (exists $$module{$zone}   &&  $alias eq $zone);
      next  if (exists $$aliases{$zone}  &&  $$aliases{$zone}[1] ne "tzdata");
      next  if (exists $$alias2{$zone});

      print $pod " "x5,$alias," "x(35-length($alias)),"  $zone\n";
      $alias = lc($alias);
      $zone  = lc($zone);
      print $out "  '$alias'" . " "x(25-length($alias)) . "=> '$zone',\n";
   }

   # Do the EST5EDT style aliases

   print $pod "
There are a large number of possible time zone aliases of the form
EST5EDT. The main 4 used in the United States are CST6CDT, EST5EDT,
MST7MDT, and PST8PDT and these are specifically called for in RFC 822,
so there is no ambiguity there, but some aliases may possibly refer to
more than one time zone. In these instances, I have selected one of
them to be the default time zone to use (based on how recently it was
used, and for what period of time). In the list below, all possible
time zones are listed for each alias. The first time zone listed is the
one used by default. The default alias can be overridden as described
above.

";

   ($alias,$zone) = ("ALTERNATE NAME","TIME ZONE");
   print $pod " "x5,$alias," "x(35-length($alias)),"  $zone\n";
   print $pod " "x5,"-"x35,"  ","-"x8,"\n\n";

   foreach $alias (sort keys %$alias2) {
      my @zone = sort keys %{ $$alias2{$alias} };
      if ($#zone == 0) {
         $zone = $zone[0];

         print $pod " "x5,$alias," "x(35-length($alias)),"  $zone\n";
         $alias = lc($alias);
         $zone  = lc($zone);
         print $out "  '$alias'" . " "x(25-length($alias)) . "=> '$zone',\n";
      }
   }

   print $pod "\n";

   ALIAS: foreach $alias (sort keys %$alias2) {
      # @zone, %zone contain all the zones that $alias (EST5EDT) is in
      my @zone = sort keys %{ $$alias2{$alias} };
      next  if ($#zone == 0);
      my %zone = map { $_,1 } @zone;

      # @def, %def contain the zones that we've listed (so we know that
      # we've made a decision based on all zones)
      my @def  = (exists $def_alias2{$alias} ? @{ $def_alias2{$alias} } : ());
      my $i    = 0;
      my %def  = map { $_,$i++ } @def;

      # %zone and %def must be identical
      my $err = 0;
      foreach my $z (@zone) {
         if (! exists $def{$z}) {
            $err = 1;
            next;
         }
         delete $def{$z};
      }
      if (! $err) {
         my @tmp = keys %def;
         $err = 1  if (@tmp);
      }

      # If they're not identical, warn
      if ($err) {
         my @tmp;
         foreach my $z (@zone,keys %def) {
            my($y0,$y1) = ("","");
            if (exists $zone{$z}) {
               my @y       = @{ $$alias2{$alias}{$z} };
               if ($#y == 0) {
                  $y0      = $y[0];
                  $y1      = $y0;
               } else {
                  $y0      = $y[0];
                  $y1      = $y[$#y];
               }
            }
            $y0      =~ s/-\d{4}$//;
            $y1      =~ s/\d{4}-//;

            push(@tmp,[$z,$y0,$y1]);
         }

         warn "[zone_alias] no default\n";
         warn "   \042$alias\042" . " "x(14-length($alias)) . "=> [\n";

         @tmp = sort { _cmp_offsets($a,$b) } @tmp;

         my $blank   = " "x23;
         foreach my $tmp (@tmp) {
            my($z,$y0,$y1) = @$tmp;
            if ($y0 == $y1) {
               $y1 = "";
            } else {
               $y1 = "-$y1";
            }
            warn "$blank\042$z\042," . " "x(39-length($z)) . "\043 $y0$y1\n";
         }
         warn " "x22 . "],\n";

         next ALIAS;
      }

      # If they are identical, add them to the pod and module

      my $first = 1;
      foreach my $z (@def) {
         my $a   = lc($alias);
         my $lcz = lc($z);
         print $out "  '$a'" . " "x(25-length($a)) . "=> '$lcz',\n"
           if ($first);

         $a = ($first ? $alias : " "x(length($alias)));
         print $pod " "x5,$a," "x(35-length($a)),"  $z\n";
         $first = 0;
      }
   }

   # Print out alternate time zone names other sources

   print $pod "
There are also a number of standard aliases. Some of these are
included to fix minor issues with the tzdata files. Others come from
standard sources including RFC 822 or the list of time zone names used
on Microsoft Windows operating systems.

Aliases include:

";

   ($alias,$zone) = ("ALTERNATE NAME","TIME ZONE");
   print $pod " "x5,$alias," "x(35-length($alias)),"  $zone\n";
   print $pod " "x5,"-"x35,"  ","-"x8,"\n\n";

   foreach $alias (sort keys %$aliases) {
      my($type);
      ($zone,$type) = @{ $$aliases{$alias} };
      next  if ($type eq "tzdata"  ||  $type eq "ignore");

      # Don't duplicate the 'zone => zone' aliases
      next  if (exists $$module{$zone}   &&  $alias eq $zone);

      print $pod " "x5,$alias," "x(35-length($alias)),"  $zone\n";
      $alias = lc($alias);
      $zone  = lc($zone);
      print $out "  '$alias'" . " "x(25-length($alias)) . "=> '$zone',\n";
   }

   print $out ");
";
}

sub _do_zones_defaults { my($out,$pod,$data2) = @_;

   # Start the defaults (POD only)

   print $pod "
Periodically, we need to be able to determine a time zone based on an
offset. In addition, the ISDST may be known, and a date/time may be
available. The following table shows what time zones are examined based
on the offset, and in what order. The first match is used. If the
ISDST time is not known, the standard zones will be tested followed by
the DST zones.

The default order can be overridden with the off_zones method in the Date::Manip::TZ module.

";

   my($isdst,$off,$zone) = ("ISDST","OFFSET","TIME ZONE");
   print $pod " "x5," "x(5-length($isdst)),$isdst,"  ",
     " "x(10-length($off)),$off,"  $zone\n";
   print $pod " "x5,"-"x5,"  ","-"x10,"  ","-"x8,"\n\n";

   foreach $isdst (0,1) {

      foreach $off (sort { _cmp_zoneoffsets($a,$b) } keys %$data2) {
         next  unless (exists $$data2{$off}{$isdst});
         my @zone = @{ $$data2{$off}{$isdst} };
         my $dst  = $isdst;
         $zone    = shift(@zone);
         print $pod " "x5,$dst," "x(5-length($dst)),"  ",
           " "x(10-length($off)),$off,"  $zone\n";
         $off = "";
         $dst = " ";
         foreach $zone (@zone) {
            print $pod " "x5,$dst," "x(5-length($dst)),"  ",
              " "x(10-length($off)),$off,"  $zone\n";
         }
      }
      print $pod "\n";
   }
}

sub _cmp_zoneoffsets { my($x,$y) = @_;

   # A negative offset comes before a positive one

   if      ($x =~ /^-/  &&  $y =~ /^\+/) {
      return -1;
   } elsif ($y =~ /^-/  &&  $x =~ /^\+/) {
      return +1;
   }

   # Netgative offsets are sorted reverse.

   if ($x =~ /^-/) {
      return ($y cmp $x);
   }

   # Positive offsets are sorted normally.

   return ($x cmp $y);
}

sub _do_zones_abbrevs { my($out,$pod) = @_;

   my $abbrev = _yaml_read("tzdata/_abbrev");

   # Start the aliases output (both POD and module)

   print $out "
\%Abbrev = (
";

   # Print out EST => ZONE aliases for abbreviations which only occur
   # in a single zone.

   print $pod "
In the time zone definitions, abbreviations are used to specify the
current time (e.g. EST in the America/New_York time zone). In some
cases, the abbreviation appears in only a single time zone. In that
case, these abbreviations may be used to refer to that time zone.  The
abbreviations LMT and zzz which occur in the zoneinfo databases are
ignored (and when parsing a date including them, the local time zone
will be used).  Abbreviations include the following:

";

   my($abb,$zone) = ("ALIAS","TIME ZONE");
   print $pod " "x5,$abb," "x(15-length($abb)),"  $zone\n";
   print $pod " "x5,"-"x15,"  ","-"x8,"\n\n";

   my (@abb) = sort keys %$abbrev;
   foreach $abb (@abb) {
      my(@zone) = sort keys %{ $$abbrev{$abb} };
      if ($#zone == 0) {
         delete $$abbrev{$abb};
         $zone = $zone[0];
         print $pod " "x5,$abb," "x(15-length($abb)),"  $zone\n";
         $abb   = lc($abb);
         $zone  = lc($zone);
         print $out "  '$abb'" . " "x(10-length($abb)) . "=> [ '$zone' ],\n";
      }
   }

   # Print out EST => ZONE aliases for abbreviations which occur in
   # multiple zones.

   print $pod "
Most abbreviations are used in multiple time zones. When a date is
parsed that contains one of these abbreviations, it will try to
interpret the date using each of the time zones in the order listed
below until one is found which yields a valid date.

The default order can be overridden using the abbrev method of the Date::Manip::TZ module.

The order given here is open to discussion (and possible change) for some unspecified period of time (possibly the first couple releases in the 6.xx cycle), but at some point, the order will become fixed. Please note that I will always place emphasis on a time zone that used the abbreviation more recently than another time zone. Within those constraints, I'm interested in putting the more commonly used time zone at a higher priority. Since I'm not always able to decide which is the most commonly used, I'm very willing to entertain arguments for altering the order.

";

   ($abb,$zone) = ("ALIAS","TIME ZONE");
   print $pod " "x5,$abb," "x(15-length($abb)),"  $zone\n";
   print $pod " "x5,"-"x15,"  ","-"x8,"\n\n";

   (@abb) = sort keys %$abbrev;
 ABB: foreach $abb (@abb) {
      # @zone, %zone contain all the zones that $abb (EST) is in
      my(@zone) = sort keys %{ $$abbrev{$abb} };
      my %zone  = map { $_,1 } @zone;

      # @def, %def contain the zones that we've listed (so we know that
      # we've made a decision based on all zones)
      my @def  = (exists $def_abbrev{$abb} ? @{ $def_abbrev{$abb} } : ());
      my $i    = 0;
      my %def  = map { $_,$i++ } @def;

      # %zone and %def must be identical
      my $err = 0;
      foreach my $z (@zone) {
         if (! exists $def{$z}) {
            $err = 1;
            next;
         }
         delete $def{$z};
      }
      if (! $err) {
         @def = keys %def;
         $err = 1  if (@def);
      }

      # If they're not identical, warn
      if ($err) {
         my @tmp;
         foreach my $z (@zone) {
            my($y0,$y1) = ("","");
            if (exists $zone{$z}) {
               my @y       = @{ $$abbrev{$abb}{$z} };
               if ($#y == 0) {
                  $y0      = $y[0];
                  $y1      = $y0;
               } else {
                  $y0      = $y[0];
                  $y1      = $y[$#y];
               }
            }
            $y0      =~ s/-\d{4}$//;
            $y1      =~ s/\d{4}-//;

            push(@tmp,[$z,$y0,$y1]);
         }

         warn "[zone_abbrev] no default\n";
         warn "   \042$abb\042" . " "x(12-length($abb)) . "=> [\n";

         @tmp = sort { _cmp_offsets($a,$b) } @tmp;

         my $blank   = " "x21;
         foreach my $tmp (@tmp) {
            my($z,$y0,$y1) = @$tmp;
            if ($y0 == $y1) {
               $y1 = "";
            } else {
               $y1 = "-$y1";
            }
            warn "$blank\042$z\042," . " "x(41-length($z)) . "\043 $y0$y1\n";
         }
         warn " "x20 . "],\n";

         next ABB;
      }

      @zone  = @{ $def_abbrev{$abb} };
      $zone  = shift(@zone);
      print $pod " "x5,$abb," "x(15-length($abb)),"  $zone\n";
      $abb   = lc($abb);
      $zone  = lc($zone);
      print $out "  '$abb'" . " "x(10-length($abb)) . "=> [ '$zone',\n";

      $abb   = "";
      foreach $zone (@zone) {
         print $pod " "x5,$abb," "x(15-length($abb)),"  $zone\n";
         $abb    = lc($abb);
         my $end = ($zone eq $zone[$#zone] ? " ]," : ",");
         $zone = lc($zone);
         print $out " "x19 . "'$zone'$end\n";
      }
   }

   print $out "
);
";
}

sub _do_zones_offsets { my($out,$pod) = @_;

   my $offmod = _yaml_read("tzdata/_offmod");

   # Start the offset output (in this case, no POD output since it
   # doesn't seem usefule.

   print $out "
\%Offmod = (
";

   foreach my $offset (sort keys %$offmod) {
      my $mod = $$offmod{$offset};
      print $out "  '$offset'" . " "x(10-length($offset)) . "=> '$mod',\n";
   }

   print $out "
);
";
}

############################################################################ # DO_CLEAN ############################################################################

sub do_clean { print "Cleaning...\n"; system("rm -rf tzdata"); }

############################################################################

sub _yaml_read { my($file) = @_; return {} if (! -e $file); my($data) = YAML::LoadFile($file); return {} if (! defined $data); return $data; }

sub _yaml_write { my($data,$file,$backup) = @_;

   rename($file,"$file.bak")  if ($backup  &&  -e $file);
   YAML::DumpFile($file,$data);
}

# Local Variables: # mode: cperl # indent-tabs-mode: nil # cperl-indent-level: 3 # cperl-continued-statement-offset: 2 # cperl-continued-brace-offset: 0 # cperl-brace-offset: 0 # cperl-brace-imaginary-offset: 0 # cperl-label-offset: -2 # End: