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

Greetings,

I seem to be able to get just about any Date calculation I need except calculating for example the first day of the month or the first monday of the month.

Date::Calc has this fuction:

Monday_of_Week ($year,$month,$day) = Monday_of_Week($week,$year);

then it states

In case you do not understand this, never mind, but then simply DO NOT USE this function in scalar context!
($year,$month,$day) = Monday_of_Week($week,$year);
This function returns the date of the first day of the given week, i.e., the Monday. "$year" must be greater than or equal to "1", and "$week" must lie in the range "1" to "Weeks_in_Year($year)".
Note that you can write "($year,$month,$day) = Monday_of_Week(Week_of_Year($year,$month,$day));" in order to calculate the date of the Monday of the same week as the given date. If you want to calculate any other day of week in the same week as a given date, use

OK How do I use this? Can any one give me a real life example of this function or something that will return the first day of the month.

Thanks for any help.

Tim

Replies are listed 'Best First'.
Re: getting the First day of the month
by pzbagel (Chaplain) on Aug 02, 2003 at 21:57 UTC

    Your question is a little confusing, you ask how to get the first day of the month and then cut-and-paste Date::Calc instructions on figuring out the first Monday of a week. If you want the first day of the month, simply refer to is with the number '1'. No Data::Calc required, that's always the first day.

    Now how to figure the first Monday of a given month? It takes a little logic, what the Date::Calc instructions are explaining is how to get the Monday of any given week, now if you want the first Monday of the month you should check Monday_of_Week() of the first day of a month. If the result is in the same month, you got lucky and Monday falls on the first, if not, increment the week of the year by 1 and you will have your answer.

    #$year, $month, and $day are set to the first of any given month my ($week,undef)=Week_of_Year($year,$month,$day); my (undef, $tmpmonth, $firstmonday)=Monday_of_Week($week,$year); if ($tmpmonth != $month) { (undef, undef, $firstmonday)=Monday_of_Week(++$week,$year); } #$firstmonday now contains the date of the first Monday of a given mon +th. #Put this in a loop or a sub or whatever and you can call it with argu +ments. print "First monday of $month/$year is $firstmonday\n";
      Thanks vroom, When I plug this into a loop I am getting these results . I am confused. They are all Mondays but just not always the first Monday.
      foreach my $item (1..12) { my $year = 2003; my $month = $item; my $day = 12; my ($week,undef)=Week_of_Year($year,$month,$day); my (undef, $tmpmonth, $firstmonday)=Monday_of_Week($week,$year); if ($tmpmonth != $month) { (undef, undef, $firstmonday)=Monday_of_Week(++$week,$year); }
      First monday of 1/2003 is 6
      First monday of 2/2003 is 10
      First monday of 3/2003 is 10
      First monday of 4/2003 is 7
      First monday of 5/2003 is 12
      First monday of 6/2003 is 9
      First monday of 7/2003 is 7
      First monday of 8/2003 is 11
      First monday of 9/2003 is 8
      First monday of 10/2003 is 6
      First monday of 11/2003 is 10
      First monday of 12/2003 is 8
        I see now. You want a list of 12 dates, each one the first Monday of the month. Personally, i am not a huge fan of Date::Calc, and prefer Time::Piece and DateTime. Here is some code that uses the latter:
        use strict; use warnings; use DateTime; my $year = DateTime->now->year; for my $month (1..12) { my $dt = DateTime->new(year => $year, month => $month); $dt->add(days => 1) until $dt->day_of_week == 1; printf "First monday of %02d/%d is %s\n", $dt->month, $dt->year, $dt->day, ; } __END__ First monday of 01/2003 is 6 First monday of 02/2003 is 3 First monday of 03/2003 is 3 First monday of 04/2003 is 7 First monday of 05/2003 is 5 First monday of 06/2003 is 2 First monday of 07/2003 is 7 First monday of 08/2003 is 4 First monday of 09/2003 is 1 First monday of 10/2003 is 6 First monday of 11/2003 is 3 First monday of 12/2003 is 1
        (psst ... that was pzbagel you replied to, not vroom ;))

        jeffa

        L-LL-L--L-LL-L--L-LL-L--
        -R--R-RR-R--R-RR-R--R-RR
        B--B--B--B--B--B--B--B--
        H---H---H---H---H---H---
        (the triplet paradiddle with high-hat)
        

        Ummm, first off my name is pzbagel, not vroom.

        Secondly, $day should be set to 1 and not 12 as you have set it. That is why you are getting the wrong Monday in your loop. Change $day to 1 and you will be set.

Re: getting the First day of the month
by bobn (Chaplain) on Aug 02, 2003 at 21:48 UTC

    Time::Local gives the first day of the month:

    use Time::Local; my $time = timelocal(0,0,0,1,7,2003); my $day .= localtime($time); print $day, "\n";
    which outputs:
    Fri Aug 1 00:00:00 2003
    Note that the days number from 1, but months number from 0.

    Using the list output of localtime would give you a day of the week numeral that you could use to calculate the first Monday.

    --Bob Niederman, http://bob-n.com
(jeffa) Re: getting the First day of the month
by jeffa (Bishop) on Aug 02, 2003 at 23:48 UTC
    "Can any one give me a real life example of this function [Monday_of_Week]..."

    Yes. See I Don't Like Mondays. But if you want the first day of the month that doesn't have to be Monday, then it's not too hard with Time::Piece:

    sub last_day { my $t = localtime; $t += Time::Piece::ONE_DAY * ($t->month_last_day - $t->mday + 1); return $t->fullday; }
    Which, if run during this month, will print 'Monday' ... go figure. ;)

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)