#!/usr/bin/perl -w
#---------#---------#---------#---------#---------#---------#---------#---------
#
# title
#   date functions
# author
#   idc@planetlarg.net 20 April 2001
# description
#   A bare program that does very little. It is intended to cut down the
#   development time of a command line tool written in perl.
#   It provides date utilities.
#   Copy and paste this for a quick way to make it look like you have been
#   working hard.
#   This should really be in a module.
# modifications
#
#---------#---------#---------#---------#---------#---------#---------#---------
# setup
#   This is the cup of tea stage, useful for do a little sorting out before
#   getting down to some real work.

   use 5.005;
   use strict;
# command line options
      # read any options entered with this program.
   &usage if $#ARGV != -1;

#---------#---------#---------#---------#---------#---------#---------#---------
# main
#   The main program goes here.

   my %date_hash = &format_date (time);
   print
               'The date today is ',
               $date_hash{year},
               $date_hash{mon},
               $date_hash{mday},
               "\n",
   ;

   my $delta   = &date_range (
               '07/Mar/2001:02:00',
               '07/Mar/2001:15:45',
   );
   print "   \$delta \t$delta \n";

#---------#---------#---------#---------#---------#---------#---------#---------
# subs
#   all subroutines go below here.

# subroutine
#  date_range
# description
#  use the biggest fattest and slowest CPAN date module available.
#  dates must be supplied in a format understood by Date::Manip
#  which is a lot: all the standards in ISO 8601 and several more.
#
sub date_range {

   my $opt_s   = shift; # start date
   my $opt_e   = shift;

   use Date::Manip;
   &Date_Init("Language=English","DateFormat=nonUS");

   #   logfile timestamp and entry is in this format:
   #   "[07/Mar/2001:13:46:48 +0000] bla bla bla ..."

#   my $start   = &ParseDate('07/Mar/2001:02:00');
#   my $end     = &ParseDate('07/Mar/2001:15:45');
   my $start   = &ParseDate($opt_s);
   my $end     = &ParseDate($opt_e);

# date checks
   if ( (! $start) or (! $end) ) {
      # Error in the date
      print "error in dates \n";
      print "   \$start \t$start \n";
      print "   \$end \t$end \n";
   }
   die "log time period is rubbish.  \n" if ($start_time > $end_time);

# range
   my $delta=&DateCalc($start,$end,\$err);
   return $delta;
}



# subroutine
#  matching_logs
# description
#  Find yesterdays logs by examining the filenames only,
#  so no last modified checks and no reading the head or tail lines of a log.
#  Stick yesterday's date on a filename glob and list matching files.
#
#  Assumes we are in the correct directory. Doesn't check the results.
sub matching_logs {

   my %yesterday     = &format_date (time - 86400);
   #  errors.<DDMMM>-<HHHH> eg. errors.11Nov-01AM
   my $LOG_GLOB  = "errors.$yesterday{mday}$yesterday{mon_abbr}-*";
   my @logs          = glob("$LOG_GLOB");

   print "\$LOG_GLOB $LOG_GLOB \n" if $DEBUG;
   print "\@logs         @logs         \n" if $DEBUG;

   return @logs;
}

# subroutine
#  format_date
# description
#  take a time in seconds since Jan 01 1970, called the epoch for
#  some stoner reason.
#  translate it to a load of human-readable date-related values
#  and shove these values into a hash.
#  This is almost the same as using the standard module Time::localtime
#
#  This is what I'm aiming for. The "-" attributes are not yet done.
#  Description                    Attribute Example
#  -------------------------------------------------
#  Year,         Full Digits      year_full 2000
#  Year,         Abbreviated      year_abbr 00
#  Month,        Full Text        mon-full  February
#  Month,        Appreviated      mon_abbr  Feb
#  Month,        Numeric          mon       02
#  Day of week                    day_full  Friday
#  Day of week,  Numeric          wday      02
#  Day,          abbreviated      day_abbr  Fri
#  Day of month, Numeric          mday      07
#  Day of year,  numeric          yday      48
#  Hours,        24 hour          hour      23
#  Hours,        12 hour          -         11
#  Minutes,      Numeric          min       21
#  Seconds,      Numeric          sec       59
#  Seconds,      Since Epoch      unix      924353322
#  AM or PM                       -         AM
#  am or pm                       -         am
#
sub format_date {
   my $unix_secs     = shift; # integer eg.987516249
   my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst)
                     = ( localtime ($unix_secs) );
      # months
   my @months_abbr   = qw (
               Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
   );
   my $mon_abbr      = $months_abbr[$mon];
   my @months_full = (
               "January","February","March","April","May","June",
               "July","August","September","October","November","December"
   );
   my $mon_full      = $months_full[$mon];
   # translate from struct tm rubbish to human
   $mon++;                    # month number starts funny (from 0 to 11)
   $mon              = "0$mon" if ($mon < 10); # month is now always 2 digits
   $mday             = "0$mday" if ($mday < 10); # and month day is 2 digits

# TESTING
      # days
# IS $wday 0 TO 6  OR  1 TO 7? BECAUSE THERE IS NO ELEMENT 7 IN THE LIST
   my @days_full     = qw (
               Sunday Monday Tuesday Wednesday Thursday Friday Saturday
   );
   my $day_full      = $days_full[$wday];
   my @days_abbr     = qw (Sun Mon Tue Wed Thu Fri Sat);
   my $day_abbr      = $days_abbr[$wday];
# TESTING


      #years
   my $year_full     =  $year + 1900; # year is now cool for Y2K
   $year_full        =~ m/\d\d(\d\d)/; # pick out last two digits
   my $year_abbr     =  $1;
   my %date_hash     =  (
               'sec'       => $sec,
               'min'       => $min,
               'hour'      => $hour,
               'mday'      => $mday,
               'mon'       => $mon,
               'mon_abbr'  => $mon_abbr,
               'mon_full'  => $mon_full,
               'year_full' => $year_full,
               'year_abbr' => $year_abbr,
               'wday'      => $wday,
               'day_abbr'  => $day_abbr,
               'day_full'  => $day_full,
               'yday'      => $yday,
               'isdst'     => $isdst,
               'unix'      => $unix_secs,
   );


=begin testing
# to use this test printout, comment out the "=begin" and "=end" tags.

print "
               'sec'       => $sec,
               'min'       => $min,
               'hour'      => $hour,
               'mday'      => $mday,
               'mon'       => $mon,
               'mon_abbr'  => $mon_abbr,
               'mon_full'  => $mon_full,
               'year_full' => $year_full,
               'year_abbr' => $year_abbr,
               'wday'      => $wday,
               'day_abbr'  => $day_abbr,
               'day_full'  => $day_full,
               'yday'      => $yday,
               'isdst'     => $isdst,
               'unix'      => $unix_secs,
";
=end testing
=cut

   return %date_hash;
}


# subroutine
#   usage
# description
#   describe how this script should be used.
#   This is one way of producing a set of instructions, using simple indentation.
#   For more complex document, use mark-up. See the perldoc section below.
#
sub usage {

   use Text::Wrap;
   $Text::Wrap::columns = 60;
   my $pre1             = "   ";
   my $pre2             = "   ";
   my $name             = "$0 - Accept and print command line options.";
   my $synopsis         = "$0  -a value  -b value";
   my $description      = <<EOD;
This does bugger all except show off a few date related functions.

You can copy this script to provide a framework for other perl scripts.
Fill in the gaps with your creativity.

For another example of documentation, try this: perldoc $0
EOD
   my $examples         = <<EOE;
none as yet.
EOE

   print
               "NAME \n",
               wrap ($pre1, $pre2, $name), "\n",
               "SYNOPSIS \n",
               wrap ($pre1, $pre2, $synopsis), "\n",
               "DESCRIPTION \n",
               fill ($pre1, $pre2, $description), "\n",
               "EXAMPLES \n",
               wrap ($pre1, $pre2, $examples), "\n",
   ;
   exit 1;
}
#---------#---------#---------#---------#---------#---------#---------#---------


__END__

documentation

The "__END__" string is a token. It is the logical end of program text.
You can put anything you want after this token, such as an
instruction manual page; it will be ignored by the compiler.

