Blame lib/Date/Manip/TZ_Base.pm

Packit 95306a
package Date::Manip::TZ_Base;
Packit 95306a
# Copyright (c) 2010-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
Packit 95306a
require 5.010000;
Packit 95306a
use warnings;
Packit 95306a
use strict;
Packit 95306a
use IO::File;
Packit 95306a
Packit 95306a
our ($VERSION);
Packit 95306a
$VERSION='6.60';
Packit 95306a
END { undef $VERSION; }
Packit 95306a
Packit 95306a
########################################################################
Packit 95306a
# METHODS
Packit 95306a
########################################################################
Packit 95306a
Packit 95306a
sub _config_var {
Packit 95306a
   my($self,$var,$val) = @_;
Packit 95306a
   $var = lc($var);
Packit 95306a
Packit 95306a
   # A simple flag used to force a new configuration, but has
Packit 95306a
   # no other affect.
Packit 95306a
   return  if ($var eq 'ignore');
Packit 95306a
Packit 95306a
   my $istz     = ref($self) eq 'Date::Manip::TZ';
Packit 95306a
Packit 95306a
   if ($istz  &&  ($var eq 'tz'         ||
Packit 95306a
                   $var eq 'forcedate'  ||
Packit 95306a
                   $var eq 'setdate'    ||
Packit 95306a
                   $var eq 'configfile')) {
Packit 95306a
      if ($var eq 'tz') {
Packit 95306a
         warn "WARNING: the TZ Date::Manip config variable is deprecated\n" .
Packit 95306a
              "         and will be removed in March 2017.  Please use\n" .
Packit 95306a
              "         the SetDate or ForceDate config variables instead.\n";
Packit 95306a
      }
Packit 95306a
      return $self->_config_var_tz($var,$val);
Packit 95306a
   } else {
Packit 95306a
      my $base  = ($istz ? $$self{'base'} : $self);
Packit 95306a
      return $base->_config_var_base($var,$val);
Packit 95306a
   }
Packit 95306a
}
Packit 95306a
Packit 95306a
# This reads a config file
Packit 95306a
#
Packit 95306a
sub _config_file {
Packit 95306a
   my($self,$file) = @_;
Packit 95306a
Packit 95306a
   return  if (! $file);
Packit 95306a
Packit 95306a
   if (! -f $file) {
Packit 95306a
      warn "ERROR: [config_file] file doesn't exist: $file\n";
Packit 95306a
      return;
Packit 95306a
   }
Packit 95306a
   if (! -r $file) {
Packit 95306a
      warn "ERROR: [config_file] file not readable: $file\n";
Packit 95306a
      return;
Packit 95306a
   }
Packit 95306a
Packit 95306a
   my $in = new IO::File;
Packit 95306a
   if (! $in->open($file)) {
Packit 95306a
      warn "ERROR: [config_file] unable to open file: $file: $!\n";
Packit 95306a
      return;
Packit 95306a
   }
Packit 95306a
   my @in = <$in>;
Packit 95306a
   $in->close();
Packit 95306a
Packit 95306a
   my $sect = 'conf';
Packit 95306a
   my %sect;
Packit 95306a
Packit 95306a
   chomp(@in);
Packit 95306a
   foreach my $line (@in) {
Packit 95306a
      $line =~ s/^\s+//o;
Packit 95306a
      $line =~ s/\s+$//o;
Packit 95306a
      next  if (! $line  or  $line =~ /^\043/o);
Packit 95306a
Packit 95306a
      if ($line =~ /^\*/o) {
Packit 95306a
         # New section
Packit 95306a
         $sect = $self->_config_file_section($line);
Packit 95306a
      } else {
Packit 95306a
         $sect{$sect} = 1;
Packit 95306a
         $self->_config_file_var($sect,$line);
Packit 95306a
      }
Packit 95306a
   }
Packit 95306a
Packit 95306a
   # If we did a holidays section, we need to create a regular
Packit 95306a
   # expression with all of the holiday names.
Packit 95306a
Packit 95306a
   my $istz  = ref($self) eq 'Date::Manip::TZ';
Packit 95306a
   my $base  = ($istz ? $$self{'base'} : $self);
Packit 95306a
Packit 95306a
   if (exists $sect{'holidays'}) {
Packit 95306a
      my @hol = @{ $$base{'data'}{'sections'}{'holidays'} };
Packit 95306a
      my @nam;
Packit 95306a
      while (@hol) {
Packit 95306a
         my $junk = shift(@hol);
Packit 95306a
         my $hol  = shift(@hol);
Packit 95306a
         push(@nam,$hol)  if ($hol);
Packit 95306a
      }
Packit 95306a
Packit 95306a
      if (@nam) {
Packit 95306a
         @nam    = sort _sortByLength(@nam);
Packit 95306a
         my $hol = '(?<holiday>' . join('|',map { "\Q$_\E" } @nam) . ')';
Packit 95306a
         my $yr  = '(?<y>\d\d\d\d|\d\d)';
Packit 95306a
Packit 95306a
         my $rx  = "$hol\\s*$yr|" .      # Christmas 2009
Packit 95306a
                   "$yr\\s*$hol|" .      # 2009 Christmas
Packit 95306a
                   "$hol";               # Christmas
Packit 95306a
Packit 95306a
         $$base{'data'}{'rx'}{'holidays'} = qr/^(?:$rx)$/i;
Packit 95306a
      }
Packit 95306a
   }
Packit 95306a
}
Packit 95306a
Packit 95306a
sub _config_file_section {
Packit 95306a
   my($self,$line) = @_;
Packit 95306a
Packit 95306a
   my $istz  = ref($self) eq 'Date::Manip::TZ';
Packit 95306a
   my $base  = ($istz ? $$self{'base'} : $self);
Packit 95306a
Packit 95306a
   $line    =~ s/^\*//o;
Packit 95306a
   $line    =~ s/\s*$//o;
Packit 95306a
   my $sect = lc($line);
Packit 95306a
   if (! exists $$base{'data'}{'sections'}{$sect}) {
Packit 95306a
      warn "WARNING: [config_file] unknown section created: $sect\n";
Packit 95306a
      $base->_section($sect);
Packit 95306a
   }
Packit 95306a
   return $sect;
Packit 95306a
}
Packit 95306a
Packit 95306a
sub _config_file_var {
Packit 95306a
   my($self,$sect,$line) = @_;
Packit 95306a
Packit 95306a
   my $istz  = ref($self) eq 'Date::Manip::TZ';
Packit 95306a
   my $base  = ($istz ? $$self{'base'} : $self);
Packit 95306a
Packit 95306a
   my($var,$val);
Packit 95306a
   if ($line =~ /^\s*(.*?)\s*=\s*(.*?)\s*$/o) {
Packit 95306a
      ($var,$val) = ($1,$2);
Packit 95306a
   } else {
Packit 95306a
      die "ERROR: invalid Date::Manip config file line:\n  $line\n";
Packit 95306a
   }
Packit 95306a
Packit 95306a
   if ($sect eq 'conf') {
Packit 95306a
      $var = lc($var);
Packit 95306a
      $self->_config($var,$val);
Packit 95306a
   } else {
Packit 95306a
      $base->_section($sect,$var,$val);
Packit 95306a
   }
Packit 95306a
}
Packit 95306a
Packit 95306a
# $val = $self->config(VAR);
Packit 95306a
#    Returns the value of a variable.
Packit 95306a
#
Packit 95306a
# $self->config([SECT], VAR, VAL)  sets the value of a variable
Packit 95306a
#    Sets the value of a variable.
Packit 95306a
#
Packit 95306a
sub _config {
Packit 95306a
   my($self,$var,$val) = @_;
Packit 95306a
Packit 95306a
   my $sect = 'conf';
Packit 95306a
Packit 95306a
   #
Packit 95306a
   # $self->_conf(VAR, VAL)  sets the value of a variable
Packit 95306a
   #
Packit 95306a
Packit 95306a
   $var = lc($var);
Packit 95306a
   if (defined $val) {
Packit 95306a
      return $self->_config_var($var,$val);
Packit 95306a
   }
Packit 95306a
Packit 95306a
   #
Packit 95306a
   # $self->_conf(VAR)       returns the value of a variable
Packit 95306a
   #
Packit 95306a
Packit 95306a
   if (exists $$self{'data'}{'sections'}{$sect}{$var}) {
Packit 95306a
      return $$self{'data'}{'sections'}{$sect}{$var};
Packit 95306a
   } else {
Packit 95306a
      warn "ERROR: [config] invalid config variable: $var\n";
Packit 95306a
      return '';
Packit 95306a
   }
Packit 95306a
}
Packit 95306a
Packit 95306a
########################################################################
Packit 95306a
Packit 95306a
sub _fix_year {
Packit 95306a
   my($self,$y) = @_;
Packit 95306a
   my $istz     = ref($self) eq 'Date::Manip::TZ';
Packit 95306a
   my $base     = ($istz ? $self->base() : $self);
Packit 95306a
Packit 95306a
   my $method   = $base->_config('yytoyyyy');
Packit 95306a
Packit 95306a
   return $y     if (length($y)==4);
Packit 95306a
   return undef  if (length($y)!=2);
Packit 95306a
Packit 95306a
   my $curr_y;
Packit 95306a
   if (ref($self) eq 'Date::Manip::TZ') {
Packit 95306a
      $curr_y  = $self->_now('y',1);
Packit 95306a
   } else {
Packit 95306a
      $curr_y  = ( localtime(time) )[5];
Packit 95306a
      $curr_y += 1900;
Packit 95306a
   }
Packit 95306a
Packit 95306a
   if ($method eq 'c') {
Packit 95306a
      return substr($curr_y,0,2) . $y;
Packit 95306a
Packit 95306a
   } elsif ($method =~ /^c(\d\d)$/) {
Packit 95306a
      return "$1$y";
Packit 95306a
Packit 95306a
   } elsif ($method =~ /^c(\d\d)(\d\d)$/) {
Packit 95306a
      return "$1$y" + ($y<$2 ? 100 : 0);
Packit 95306a
Packit 95306a
   } else {
Packit 95306a
      my $y1      = $curr_y - $method;
Packit 95306a
      my $y2      = $y1 + 99;
Packit 95306a
      $y1         =~ /^(\d\d)/;
Packit 95306a
      $y          = "$1$y";
Packit 95306a
      if ($y<$y1) {
Packit 95306a
         $y += 100;
Packit 95306a
      }
Packit 95306a
      if ($y>$y2) {
Packit 95306a
         $y -= 100;
Packit 95306a
      }
Packit 95306a
      return $y;
Packit 95306a
   }
Packit 95306a
}
Packit 95306a
Packit 95306a
###############################################################################
Packit 95306a
# Functions for setting the default date/time
Packit 95306a
Packit 95306a
# Many date operations use a default time and/or date to set some
Packit 95306a
# or all values.  This function may be used to set or examine the
Packit 95306a
# default time.
Packit 95306a
#
Packit 95306a
# _now allows you to get the current date and/or time in the
Packit 95306a
# local timezone.
Packit 95306a
#
Packit 95306a
# The function performed depends on $op and are described in the
Packit 95306a
# following table:
Packit 95306a
#
Packit 95306a
#    $op                  function
Packit 95306a
#    ------------------   ----------------------------------
Packit 95306a
#    undef                Returns the current default values
Packit 95306a
#                         (y,m,d,h,mn,s) without updating
Packit 95306a
#                         the time (it'll update if it has
Packit 95306a
#                         never been set).
Packit 95306a
#
Packit 95306a
#    'now'                Updates now and returns
Packit 95306a
#                         (y,m,d,h,mn,s)
Packit 95306a
#
Packit 95306a
#    'time'               Updates now and Returns (h,mn,s)
Packit 95306a
#
Packit 95306a
#    'y'                  Returns the default value of one
Packit 95306a
#    'm'                  of the fields (no update)
Packit 95306a
#    'd'
Packit 95306a
#    'h'
Packit 95306a
#    'mn'
Packit 95306a
#    's'
Packit 95306a
#
Packit 95306a
#    'systz'              Returns the system timezone
Packit 95306a
#
Packit 95306a
#    'isdst'              Returns the 'now' values if set,
Packit 95306a
#    'tz'                 or system time values otherwise.
Packit 95306a
#    'offset'
Packit 95306a
#    'abb'
Packit 95306a
#
Packit 95306a
sub _now {
Packit 95306a
   my($self,$op,$noupdate) = @_;
Packit 95306a
   my $istz      = ref($self) eq 'Date::Manip::TZ';
Packit 95306a
   my $base      = ($istz ? $self->base() : $self);
Packit 95306a
Packit 95306a
   # Update "NOW" if we're checking 'now', 'time', or the date
Packit 95306a
   # is not set already.
Packit 95306a
Packit 95306a
   if (! defined $noupdate) {
Packit 95306a
      if ($op =~ /(?:now|time)/) {
Packit 95306a
         $noupdate = 0;
Packit 95306a
      } else {
Packit 95306a
         $noupdate = 1;
Packit 95306a
      }
Packit 95306a
   }
Packit 95306a
   $noupdate = 0  if (! exists $$base{'data'}{'now'}{'date'});
Packit 95306a
   $self->_update_now()  unless ($noupdate);
Packit 95306a
Packit 95306a
   # Now return the value of the operation
Packit 95306a
Packit 95306a
   my @tmpnow   = @{ $$base{'data'}{'tmpnow'} };
Packit 95306a
   my @now      = (@tmpnow ? @tmpnow : @{ $$base{'data'}{'now'}{'date'} });
Packit 95306a
Packit 95306a
   if ($op eq 'tz') {
Packit 95306a
      if (exists $$base{'data'}{'now'}{'tz'}) {
Packit 95306a
         return $$base{'data'}{'now'}{'tz'};
Packit 95306a
      } else {
Packit 95306a
         return $$base{'data'}{'now'}{'systz'};
Packit 95306a
      }
Packit 95306a
Packit 95306a
   } elsif ($op eq 'systz') {
Packit 95306a
      return $$base{'data'}{'now'}{'systz'};
Packit 95306a
Packit 95306a
   } elsif ($op eq 'isdst') {
Packit 95306a
      return $$base{'data'}{'now'}{'isdst'};
Packit 95306a
Packit 95306a
   } elsif ($op eq 'offset') {
Packit 95306a
      return @{ $$base{'data'}{'now'}{'offset'} };
Packit 95306a
Packit 95306a
   } elsif ($op eq 'abb') {
Packit 95306a
      return $$base{'data'}{'now'}{'abb'};
Packit 95306a
Packit 95306a
   } elsif ($op eq 'now') {
Packit 95306a
      return @now;
Packit 95306a
Packit 95306a
   } elsif ($op eq 'y') {
Packit 95306a
      return $now[0];
Packit 95306a
Packit 95306a
   } elsif ($op eq 'time') {
Packit 95306a
      return @now[3..5];
Packit 95306a
Packit 95306a
   } elsif ($op eq 'm') {
Packit 95306a
      return $now[1];
Packit 95306a
Packit 95306a
   } elsif ($op eq 'd') {
Packit 95306a
      return $now[2];
Packit 95306a
Packit 95306a
   } elsif ($op eq 'h') {
Packit 95306a
      return $now[3];
Packit 95306a
Packit 95306a
   } elsif ($op eq 'mn') {
Packit 95306a
      return $now[4];
Packit 95306a
Packit 95306a
   } elsif ($op eq 's') {
Packit 95306a
      return $now[5];
Packit 95306a
Packit 95306a
   } else {
Packit 95306a
      warn "ERROR: [now] invalid argument list: $op\n";
Packit 95306a
      return ();
Packit 95306a
   }
Packit 95306a
}
Packit 95306a
Packit 95306a
sub _update_now {
Packit 95306a
   my($self) = @_;
Packit 95306a
   my $istz     = ref($self) eq 'Date::Manip::TZ';
Packit 95306a
   my $base     = ($istz ? $self->base() : $self);
Packit 95306a
Packit 95306a
   # If we've called ForceDate, don't change it.
Packit 95306a
   return  if ($$base{'data'}{'now'}{'force'});
Packit 95306a
Packit 95306a
   # If we've called SetDate (which will only happen if a
Packit 95306a
   # Date::Manip:TZ object is available), figure out what 'now' is
Packit 95306a
   # based on the number of seconds that have elapsed since it was
Packit 95306a
   # set.  This will ONLY happen if TZ has been loaded.
Packit 95306a
Packit 95306a
   if ($$base{'data'}{'now'}{'set'}) {
Packit 95306a
      my $date = $$base{'data'}{'now'}{'setdate'};
Packit 95306a
      my $secs = time - $$base{'data'}{'now'}{'setsecs'};
Packit 95306a
Packit 95306a
      $date      = $base->calc_date_time($date,[0,0,$secs]);  # 'now' in GMT
Packit 95306a
      my $zone   = $self->_now('tz',1);
Packit 95306a
      my ($err,$date2,$offset,$isdst,$abbrev) = $self->convert_from_gmt($date,$zone);
Packit 95306a
Packit 95306a
      $$base{'data'}{'now'}{'date'}   = $date2;
Packit 95306a
      $$base{'data'}{'now'}{'isdst'}  = $isdst;
Packit 95306a
      $$base{'data'}{'now'}{'offset'} = $offset;
Packit 95306a
      $$base{'data'}{'now'}{'abb'}    = $abbrev;
Packit 95306a
      return;
Packit 95306a
   }
Packit 95306a
Packit 95306a
   # Otherwise, we'll use the system time.
Packit 95306a
Packit 95306a
   my $time = time;
Packit 95306a
   my($s,$mn,$h,$d,$m,$y,$wday,$yday,$isdst) = localtime($time);
Packit 95306a
   my($s0,$mn0,$h0,$d0,$m0,$y0)              = gmtime($time);
Packit 95306a
Packit 95306a
   $y += 1900;
Packit 95306a
   $m++;
Packit 95306a
Packit 95306a
   $y0 += 1900;
Packit 95306a
   $m0++;
Packit 95306a
Packit 95306a
   my $off = $base->calc_date_date([$y,$m,$d,$h,$mn,$s],[$y0,$m0,$d0,$h0,$mn0,$s0],1);
Packit 95306a
Packit 95306a
   $$base{'data'}{'now'}{'date'}  = [$y,$m,$d,$h,$mn,$s];
Packit 95306a
   $$base{'data'}{'now'}{'isdst'} = $isdst;
Packit 95306a
   $$base{'data'}{'now'}{'offset'}= $off;
Packit 95306a
Packit 95306a
   my $abb = '???';
Packit 95306a
   if (ref($self) eq 'Date::Manip::TZ') {
Packit 95306a
      my $zone   = $self->_now('tz',1);
Packit 95306a
      my $per    = $self->date_period([$y,$m,$d,$h,$mn,$s],$zone,1,$isdst);
Packit 95306a
      $abb = $$per[4];
Packit 95306a
   }
Packit 95306a
Packit 95306a
   $$base{'data'}{'now'}{'abb'}   = $abb;
Packit 95306a
Packit 95306a
   return;
Packit 95306a
}
Packit 95306a
Packit 95306a
###############################################################################
Packit 95306a
# This sorts from longest to shortest element
Packit 95306a
#
Packit 95306a
no strict 'vars';
Packit 95306a
sub _sortByLength {
Packit 95306a
   return (length $b <=> length $a);
Packit 95306a
}
Packit 95306a
use strict 'vars';
Packit 95306a
Packit 95306a
1;
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: