Ok, I finally decided to do it without any Date:: modules. Here is a working version of my script and I admit some places look a bit crude ;)
#!/usr/bin/perl
#
#
use strict;
use Time::Local;
use Text::CSV;
my $debug = 0;
my $infile;
while (@ARGV) {
$_ = shift;
/(.*\.csv$)/ && do {$infile = $1; next};
/^-d/ && do {$debug++; next};
}
my %holidays =
{
"20060101" => 1,
"20060317" => 1,
"20060414" => 1,
"20060417" => 1,
"20060501" => 1,
"20060605" => 1,
"20060807" => 1,
"20061030" => 1,
"20061225" => 1,
"20061226" => 1
};
#my @dates = ('2006/06/12 09:00:00|2006/06/16 13:00:00');
open(IF,"$infile") || die "cannot open $infile\n";
while (my $line = <IF>) {
$line =~ /^FAULT/ && next;
my $csv = Text::CSV->new;
$csv->parse($line) || die "Could not parse line:$line:$csv->error_in
+put";
my ($ref,$start,$end) = $csv->fields;
my $datepair = "$start" . "|" . "$end";
my $work_seconds = &get_work_seconds($datepair);
print "$ref,$work_seconds\n";
}
close(IF);
########################
sub get_work_seconds {
my $datepair = shift;
print "$datepair\n" if $debug;
$datepair =~ /(\d{4})\/(\d{2})\/(\d{2}) (\d{2}):(\d{2}):(\d{2})\|(\d
+{4})\/(\d{2})\/(\d{2}) (\d{2}):(\d{2}):(\d{2})/;
my ($y1,$m1,$d1,$h1,$min1,$s1) = ($1,$2,$3,$4,$5,$6);
my ($y2,$m2,$d2,$h2,$min2,$s2) = ($7,$8,$9,$10,$11,$12);
my $yyyymmdd1 = $y1 . $m1 . $d1;
my $yyyymmdd2 = $y2 . $m2 . $d2;
my ($day_start1,$day_end1) = &day_ctime_range($yyyymmdd1);
my ($day_start2,$day_end2) = &day_ctime_range($yyyymmdd2);
my $date1 = timelocal($s1,$min1,$h1,$d1,$m1-1,$y1);
my $date2 = timelocal($s2,$min2,$h2,$d2,$m2-1,$y2);
if ($date1 < $day_start1) {
$date1 = $day_start1;
}
if ($date1 > $day_end1) {
$date1 = $day_end1;
}
if ($date2 < $day_start2) {
$date2 = $day_start2;
}
if ($date2 > $day_end2) {
$date2 = $day_end2;
}
my $date1_secs = $day_end1 - $date1;
my $date2_secs = $date2 - $day_start2;
if (&non_workday($date1)) {
$date1_secs = 0;
}
if (&non_workday($date2)) {
$date2_secs = 0;
}
print "date1_secs=$date1_secs\n" if $debug;
print "date2_secs=$date2_secs\n" if $debug;
my $days = 0;
$date1 += 86400;
while ($date1 < $day_start2) {
my $nwday = &non_workday($date1);
if ($nwday == 0) {
$days++;
}
$date1 += 86400;
}
print "NUMBER_DAYS=$days\n" if $debug;
my $seconds = ((8.5 * 60 * 60) * $days) + $date1_secs + $date2_secs;
print ("((8.5 * 60 * 60) * $days) + $date1_secs + $date2_secs = $sec
+onds\n") if $debug;
return $seconds;
}
########################
sub day_ctime_range {
#for a given YYMMDD return start and end ctime
my $today = shift();
$today =~ /^(\d\d\d\d)(\d\d)(\d\d)$/;
my ($yyyy,$mm,$dd) = ($1,$2,$3);
my $start = timelocal(0,30,8,$dd,$mm-1,$yyyy-1900);
my $end = timelocal(0,0,17,$dd,$mm-1,$yyyy-1900);
return ($start,$end);
}
########################################
sub non_workday {
my ($some_time) = shift;
my $non_workday = 0;
# check if a day is a holiday
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = loc
+altime($some_time);
my $yyyy = $year+1900;
my $mm = $mon+1;
my $yyyymmdd= sprintf ("%4d%02d%02d", $yyyy, $mm, $mday);
$non_workday = 1 if exists $holidays{$yyyymmdd};
#weekend?
if ($wday == 0 || $wday == 6) {
$non_workday = 1;
}
return ($non_workday);
}
########################################
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.