Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks!
I got this Perl code from here as an example, could someone explain to me if this is right, because it seems to be wrong, (this is how Delta Days should be "Delta_Days(2002, 06, 20, 2001, 06, 20), I dont know how to used it with the ">30", but I just would like someone to explain to me what is happening there.
(Delta_Days($3, $months{$1}, $2, $today[2], $today[1], $today[0]) > 30 + )? push @log_lines, $line : keep_line($line);

Here is where this line come from and inside the while loop, once it is running it goes or runs forever
Thanks!
#!/usr/bin/perl -w use Date::Calc qw(Delta_Days); my $dirname = "."; my (@files, @log_lines); my %months = ( 'Jan' => 1, 'Feb' => 2, 'Mar' => 3, 'Apr' => 4, 'May' => 5, 'Jun' => 6, 'Jul' => 7, 'Aug' => 8, 'Sep' => 9, 'Oct' => 10, 'Nov' => 11, 'Dec' => 12, ); # get the list of text files opendir DIR, "$dirname"; @dircontent = grep { /\.txt$/ } readdir(DIR); closedir DIR; # Compute today's date my @today = (localtime(time))[3..5]; $today[1]++; $today[2] += 1900; # foreach text file, compute lines condition foreach $filename (@dircontent) { open FILE, "<$filename"; while(<FILE>) { my $line = $_; # see if line matches date format if($line =~ /^\[(\w{3}?) (\d{2}?)[^\]]*(\d{4}?)(.*)$/) { # assumed 'one month older' as being over 30 days. # if the line is older than 30 days, save it into an array # and write it later. If not, write it to a temp file (Delta_Days($3, $months{$1}, $2, $today[2], $today[1], $today[0] +) > 30 )? push @log_lines, $line : keep_line($line); } else { keep_line($line); } } close FILE; # The following lines restore the initial file but without old lines unlink $filename; rename "temp.tmp", $filename; } # archive old lines open ARCH, ">>archive.arc"; foreach $line (@log_lines) { print ARCH "$line"; } close ARCH; # Just append a line to temp file sub keep_line { my $line = shift; open TEMP, ">>temp.tmp"; print TEMP "$line"; close TEMP; }


Thanks again!

Considered by g0n: "This seems to be continuation of Comparing Dates as noted by mikeraz. Reparent in the original thread?"
Unconsidered by jdporter (3/4/0)

Replies are listed 'Best First'.
Re: Date::Calc Question
by davidrw (Prior) on Jan 30, 2006 at 16:26 UTC
    See the docs for Date::Calc:
    o "$Dd = Delta_Days($year1,$month1,$day1, $year2,$month2,$day2);"

    This function returns the difference in days between the two given dates.

    The result is positive if the two dates are in chronological order, i.e., if date #1 comes chronologically BEFORE date #2, and negative if the order of the two dates is reversed.

    The result is zero if the two dates are identical.
    So the '> 30' part, combined w/the ternary operator is saying: "if ($3, $months{$1}, $2) is more than 30 days before ($today2, $today1, $today[0]) then put $line into @log_lines, otherwise keep_line($line)"
Re: Date::Calc Question
by mikeraz (Friar) on Jan 30, 2006 at 17:05 UTC

    First, consider moving this question to the tail of your previous thread. That would maintain the flow of the conversation.

    The code ref in question,

    (Delta_Days($3, $months{$1}, $2, $today[2], $today[1], $today[0]) > 30 + )? push @log_lines, $line : keep_line($line);
    is asking
    date_diff > 30 ? move_line : keep_line
    which could be restated as
    if(date_diff > 30) { move_line; } else { keep_line; }
    That's what the ?: operator does. Delta_Days returns the number of days between two dates. So the > comparison to 30 fits your original request of finding timestamps more than a month old. [1]

    Make sense?

    [1] That is if you wish to follow the common convention that a month equals 30 days. If you need to do something like anything less than the current day of month in the previous month you'll need a different test.

    Be Appropriate && Follow Your Curiosity
Re: Date::Calc Question
by ysth (Canon) on Jan 30, 2006 at 18:38 UTC
    once it is running it goes or runs forever
    I assume your logs are pretty big. The prime culprit is probably the keep_line subroutine; move the open TEMP to before the open FILE, the close TEMP to just after the unlink $filename, and change the calls to keep_line to do the print TEMP $line.

    Another suggestion: ditch everything that uses @log_lines and just open ARCH before the foreach $filename and do the print ARCH $line instead of pushing to @log_lines.