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

Please could I have some help with the following bit of code. I need to get the times appropriately assigned to variables.
foreach ( @directories_time_tagged ) { $directory_name = $_; if ($directory_name =~ /(\d\d\d\d)_(\d\d)_(\d\d)_(\d\d)/) { # Year_ +month_day_hour $year = $1; $month = $2; $day = $3; $hour = $4; } my $date_time = ; # The time indicated by $year $month $day $ho +ur my $now = ; # Not sure how to get this value if ($date_time => $now ) # If the date has been passed { print "\nconditions have been met\n";
Update :

This is running on Windows.

Replies are listed 'Best First'.
Re: Appropriately assigning times to variables
by jettero (Monsignor) on May 02, 2007 at 10:37 UTC

    I'd probably select Time::Local there. There's a gotcha or two to lookout for though.

    my ($S, $M) = (0,0); my $H = $1 if $hour =~ m/0*(\d+)/; # I'm not sure if leading 0s hurt my $d = $1 if $day =~ m/0*(\d+)/; my $m = $1 if $month =~ m/0*(\d+)/; $m --; # gotcha! the month is 0-11 # timelocal($sec,$min,$hour,$mday,$mon,$year); my $utime = timelocal($S, $M, $H, $d, $m, $year);

    Although, in general, Date::Manip is the way to go, timelocal is a million times faster.

    -Paul

Re: Appropriately assigning times to variables
by pKai (Priest) on May 02, 2007 at 12:21 UTC

    Not exactly answering your question maybe…
    …but since your time string is perfect for pulling the time comparison into the domain of string comparison…

    use strict; use warnings; chomp(my @directories_time_tagged = <DATA>); for my $directory_name ( @directories_time_tagged ) { next unless $directory_name =~ /(\d\d\d\d_\d\d_\d\d_\d\d)/; # Year_ +month_day_hour my $date_time = $1; my ($year, $month, $day, $hour) = split /_/, $date_time; my ($y_now, $m_now, $d_now, $h_now) = (localtime)[5,4,3,2]; my $now = sprintf('%d_%02d_%02d_%02d', $y_now+1900, $m_now+1, $d_now +, $h_now); if ($date_time le $now ) { # If the date has been passed print "\nconditions have been met for $directory_name\n"; } } __DATA__ foo_2006_03_02_14_verzeichnis bar_2007_05_02_02_directory baz_2007_05_03_22_dossier
      Just a nitpick: I don't think you need to reassign a value to $now on every iteration of the loop.
      I like this code because it takes out the need for a module. The wider context for the code you have given me is:
      my (@priority_numbers_in_order, @directories_to_transport) = Search_di +rectories ($input_directory_C, $node); my $count = 0; for (@directories_to_transport){ my $priority_number = $priority_numbers_in_order[$count]; my $specific_recipient_directory = "$recipient_directory"."$priority +_number"; $dir = $_; opendir(DIR, "$dir") or die $!; my $file_name; while (<DIR>){ $file_name = $_; } my $dir_and_filename = $dir.$file_name; rename "$dir_and_filename", "C:$specific_recipient_directory/$file_n +ame" or warn $!; $count++; } sub Search_directories { my ($input_directory_CC, $node) = @_; my $directory_of_interest = "$input_directory_CC"; opendir (DIRY, "$directory_of_interest") or die "Error opening direc +tory : $!"; my @directories; while ($_ = (readdir DIRY)) { print $_, "\n"; if (-d "$input_directory_CC/$_") { print "This is a dir $_ \n"; if ($_ =~ /\d$/){ print "This directory is a number: $_"; push (@directories, $_); } } } close DIRY; print "\n\&&&&&&&&&&&&&&&&&&&&&&&&&&&&&\n".$input_directory_CC.@dire +ctories."\n\n"; for my $dir_num (@directories) { my @direcories_to_transport; print "\nforeach of the direcotories : $dir_num\n"; my $input_dir = $input_directory_CC.$dir_num; print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>$input_dir"; opendir DIRY, $input_dir or die "Error opening directory $input_ +dir - $!"; my @directories_time_tagged = grep /\d*$/, readdir DIRY; closedir DIRY; chomp(my @directories_time_tagged = <DATA>); for my $directory_name ( @directories_time_tagged ) { next unless $directory_name =~ /(\d\d\d\d_\d\d_\d\d_\d\d)/; # Yea +r_month_day_hour my $date_time = $1; my ($year, $month, $day, $hour) = split /_/, $date_time; my ($y_now, $m_now, $d_now, $h_now) = (localtime)[5,4,3,2]; my $now = sprintf('%d_%02d_%02d_%02d', $y_now+1900, $m_now+1, $d_n +ow, $h_now); if ($date_time le $now ) { # If the date has been passed print "\nconditions have been met for $directory_name\n"; my $directory_to_move = $input_directory_CC.$dir_num..$directory +_name; push (@direcories_to_transport, $directory_to_move); push (@priority_numbers_in_order, $dir_num); } } } return @priority_numbers_in_order, @direcories_to_transport; }
      I've not tested it though.
Re: Appropriately assigning times to variables
by akho (Hermit) on May 02, 2007 at 10:49 UTC
    Untested, but should work:

    use strict; use warnings; use DateTime; my @dirs = ... DIR: for my $dir (@dirs) { next DIR if (!($dir =~ /(\d{4})_(\d{2})_(\d{2})_(\d{2})/)); my $dir_time = DateTime->new( year => $1, month => $2, day => $3, hour => $4, time_zone => 'floating', ); if (0 <= DateTime->compare($dir_time, DateTime->now(time_zone => ' +floating')) { print "whatever\n"; } }
Re: Appropriately assigning times to variables
by Moron (Curate) on May 02, 2007 at 16:40 UTC
    I think the approach went astray before line 1 and the logic looks to be in reverse order from what I'd have done.

    A sensible first step (suggested in what is left hanging at the end of your code) is to convert the current time to a format that matches the directories, before doing anything with them at all (i.e. why read them into an array unfiltered - put all the filtering in one place and process in a grep/readdir loop without needing an array...)

    Update: added comments in Filter subroutine as requested by OPer

    # convert current time to same format as dirs my $now; { my @now = localtime(); $now = $now[5]+1900; $now[4]++; for ( my $i = 4; $i > 1; $i-- ) { $now .= '_'; $now[$i] = "0$now[$i]"; $now[$i] = substr( $now[$i], -2 ); $now .= $now[$i]; } } # get only those directories that match requirements: my $dir = "parent-of-directories"; opendir my $dh, $dir or die $!; for my $file ( grep Filter( now => $now, dir => $dir ), readdir $dh ) +{ my $path = "$dir/$file"; # and go right ahead and process the directory "$path" here in the +loop # ... # } closedir $dh; sub Filter { # put all filter conditions here ... my %opt = @_; ( -d "$opt{ dir }/$_" ) # is a directory && !/^\./ # is also not hidden/special && /(\d{4}_\d{2}_\d{2}_\d{2})/ # contains date/hour && ($opt{ now } gt $1 ) # that is in the past ; }
    __________________________________________________________________________________

    ^M Free your mind!

    A reply falls below the community's threshold of quality. You may see it by logging in.