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

Hi Monks!

I am working on a program that needs to print 45 days from the date given, I need to print the latest date first, can someone give me a hand on this one?!
Here is my code.

#!/perl/bin/perl use CGI qw(:standard); use CGI::Carp qw(fatalsToBrowser); use Date::Calc qw(Add_Delta_Days Day_of_Week); use strict; # DATE DROPDOWN (last 30 business days) common wherever found my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(); $mon++; $year += 1900; my (@date_dd_from,@date_dd_to); #Sample dates my $selected_date_from = "1/21/2008"; my $selected_date_to = "1/21/2008"; for (my $x = 1; $x < 45; $x++) # 45 days later { ($year,$mon,$mday) = Add_Delta_Days($year,$mon,$mday,1); my $dow = Day_of_Week($year,$mon,$mday); if (($dow != 6) && ($dow != 7)){ if ("$mon/$mday/$year" eq "$selected_date_from"){ push(@date_dd_from,"<option selected value=\"$mon/$mday/$yea +r\">$mon/$mday/$year</option>\n"); }else{ push(@date_dd_from,"<option value=\"$mon/$mday/$year\">$ +mon/$mday/$year</option>\n"); } if ("$mon/$mday/$year" eq $selected_date_to){ push(@date_dd_to,"<option selected value=\"$mon/$mday/$year\ +">$mon/$mday/$year</option>\n"); }else{ push(@date_dd_to,"<option value=\"$mon/$mday/$year\">$mo +n/$mday/$year</option>\n"); } } } print "\n@date_dd_to\n";


Thanks a lot!!!

Replies are listed 'Best First'.
Re: Getting the Latest Date Issue
by locked_user sundialsvc4 (Abbot) on Jan 22, 2008 at 22:17 UTC

    “Use the CPAN, Luke!”

    Using a module such as Date::Manip, you can solve problems like this very easily ... and do it in a very generic way.

    1. First, use one of the supplied routines to convert the date/time string into an internal date-value, automagically doing so in a manner that is appropriate for your chosen locale (corner of the world).
    2. Now loop for a date-offset from 0 to 44, or from 1 to 45 if you prefer...
    3. Use the library routine to calculate a date that is the appropriate number of days distant from the supplied date, and use another routine to convert that value into a string ... once again, appropriate to your particular corner of the planet.

    You can, for the most part, treat the entire locale-specific conversion process as a black-box, and the returned date values as an opaque scalar type. Just the way you like it...

    If it were not for CPAN, Perl would merely be “a peculiar little language.” CPAN is what makes it into a very powerful problem-solving tool. (http://search.cpan.org should be prominent in your browser bookmarks toolbar.) When you find yourself doing something like this, your gut-reaction should be to search CPAN first, where you can expect to find hundreds if not thousands of modules on almost every conceivable topic including “rocket science.”

Re: Getting the Latest Date Issue
by Herkum (Parson) on Jan 22, 2008 at 20:51 UTC
    use the DateTime module, sample/working code is below.
    use strict; use warnings; use DateTime; my $time = DateTime->new( month => 1, day => 21, year => 2008); $time->add( days => 45 ); print _option( $time->mdy(q{/}) ); for (1..45) { $time->subtract( days => 1 ); print _option( $time->mdy(q{/}) ); } sub _option { my $time = shift; return qq{<option value="$time">$time</option>\n} }
Re: Getting the Latest Date Issue
by olus (Curate) on Jan 22, 2008 at 18:46 UTC
    I'd suggest doing the things in two steps.
    1. Push the dates to an array and 'reverse' it.
    2. Foreach date do the printing.
      I can reverse it, but how could I get today's date to be printed as well, it is stating from tomorrow's date.

      my @date_dd_to_r = reverse @date_dd_to; print "\n@date_dd_to_r\n";
        You are starting with today's date and the first thing you do in your cycle is to add one day.

        To keep the cycle untouched, you should subtract one day to the initial ($year,$mon,$mday), so that the first iteration gives you today.
Re: Getting the Latest Date Issue
by apl (Monsignor) on Jan 22, 2008 at 19:19 UTC
    I'd recommend using Date::Business. There's a method that lets you add a number of days to a date, giving you a year/month/day. You could then format as necessary and do a foreach starting at the result, decrementing.
      This is printing that:

      <option selected value="3/6/2008">3/6/2008</op <option value="3/5/2008">3/5/2008</option> <option value="3/4/2008">3/4/2008</option> <option value="3/3/2008">3/3/2008</option> <option value="2/29/2008">2/29/2008</option> <option value="2/28/2008">2/28/2008</option> <option value="2/27/2008">2/27/2008</option> <option value="2/26/2008">2/26/2008</option> <option value="2/25/2008">2/25/2008</option> <option value="2/22/2008">2/22/2008</option> <option value="2/21/2008">2/21/2008</option> <option value="2/20/2008">2/20/2008</option> <option value="2/19/2008">2/19/2008</option> <option value="2/18/2008">2/18/2008</option> <option value="2/15/2008">2/15/2008</option> <option value="2/14/2008">2/14/2008</option> <option value="2/13/2008">2/13/2008</option> <option value="2/12/2008">2/12/2008</option> <option value="2/11/2008">2/11/2008</option> <option value="2/8/2008">2/8/2008</option> <option value="2/7/2008">2/7/2008</option> <option value="2/6/2008">2/6/2008</option> <option value="2/5/2008">2/5/2008</option> <option value="2/4/2008">2/4/2008</option> <option value="2/1/2008">2/1/2008</option> <option value="1/31/2008">1/31/2008</option> <option value="1/30/2008">1/30/2008</option> <option value="1/29/2008">1/29/2008</option> <option value="1/28/2008">1/28/2008</option> <option value="1/25/2008">1/25/2008</option> <option value="1/24/2008">1/24/2008</option> <option value="1/23/2008">1/23/2008</option>


      How can I get today's date to be the last one before "1/23/2008

      Thanks!!!!
        You could do a $d = new Date::Business(DATE => '20071123', OFFSET => 1 ); to get the date for the day after 01/23/2008.
        I forgot, course after doing the reverse like this:

        if (($dow != 6) && ($dow != 7)){ if ("$mon/$mday/$year" eq $selected_date_from){ push(@date_dd_from_r,"<option selec +ted value=\"$mon/$mday/$year\">$mon/$mday/$year</option>\n"); @date_d +d_from = reverse @date_dd_from_r; }else{ push(@date_dd_from_r,"<option +value=\"$mon/$mday/$year\">$mon/$mday/$year</option>\n"); + @date_dd_from = reverse @date_dd_from_r; } if ("$mon/$mday/$year" eq $selected_date_to){ push(@date_dd_to_r," +<option selected value=\"$mon/$mday/$year\">$mon/$mday/$year</option> +\n"); @date_dd +_to = reverse @date_dd_to_r; }else{ push(@date_dd_to_r,"<option va +lue=\"$mon/$mday/$year\">$mon/$mday/$year</option>\n"); + @date_dd_to = reverse @date_dd_to_r; } }

        Just need to know how to have today's date to the list.
Re: Getting the Latest Date Issue
by eric256 (Parson) on Jan 22, 2008 at 20:58 UTC

    I think you just need to change the loop to 0-45 instead of 1-45. I'll test and brb.


    ___________
    Eric Hodges

      Here is the code rewritten a bit. I would probably use CGI to generate the drop down, but this should give you an idea. I use $x as the offset and loop over it unshift (push but on the other end of the array so i don't have to reverse). This way you can do 0-45 and get exactly what you want. BTW This code does 45 days (excluding weekends), not the last 45 work days.

      #!/perl/bin/perl use CGI qw(:standard); use CGI::Carp qw(fatalsToBrowser); use Date::Calc qw(Add_Delta_Days Day_of_Week); use strict; # DATE DROPDOWN (last 30 business days) common wherever found my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(); $mon++; $year += 1900; my (@date_dd_from,@date_dd_to); #Sample dates my $selected_date_from = "1/23/2008"; my $selected_date_to = "1/23/2008"; for my $x (0..45) { # 45 days later my ($n_year,$n_mon,$n_mday) = Add_Delta_Days($year,$mon,$mday,$x) +; if (Day_of_Week($n_year,$n_mon,$n_mday) < 6) { my $date = "$n_mon/$n_mday/$n_year"; my $from_selected = $date eq $selected_date_from ? 'selected' + : ''; my $to_selected = $date eq $selected_date_to ? 'selected' + : ''; unshift @date_dd_from, "<option $from_selected value='$date'>$dat +e</option>\n"; unshift @date_dd_to, "<option $to_selected value='$date'> +$date</option>\n"; } } print "\n", @date_dd_to, "\n";

      ___________
      Eric Hodges