Saturday, October 24, 2009

5.27 Finding Dates for Weekdays of Other Weeks




I l@ve RuBoard










5.27 Finding Dates for Weekdays of Other Weeks




5.27.1 Problem



You want to compute the date for
some weekday of some other week.





5.27.2 Solution



Figure out the date for that weekday in the current week, then shift
the result into the desired week.





5.27.3 Discussion



Calculating the date for a day of the week in some other week is a
problem that breaks down into a day-within-week shift (using the
formula given in the previous section) plus a week shift. These
operations can be done in either order because the amount of shift
within the week is the same whether or not you shift the reference
date into a different week first. For example, to calculate Wednesday
of a week by the preceding formula, n is
4. To compute the date for Wednesday two weeks ago, you can perform
the day-within-week shift first, like this:



mysql> SET @target =
-> DATE_SUB(DATE_ADD(CURDATE( ),INTERVAL 4-DAYOFWEEK(CURDATE( )) DAY),
-> INTERVAL 14 DAY);
mysql> SELECT CURDATE( ), @target, DAYNAME(@target);
+------------+------------+------------------+
| CURDATE( ) | @target | DAYNAME(@target) |
+------------+------------+------------------+
| 2002-07-15 | 2002-07-03 | Wednesday |
+------------+------------+------------------+


Or you can perform the week shift first:



mysql> SET @target =
-> DATE_ADD(DATE_SUB(CURDATE( ),INTERVAL 14 DAY),
-> INTERVAL 4-DAYOFWEEK(CURDATE( )) DAY);
mysql> SELECT CURDATE( ), @target, DAYNAME(@target);
+------------+------------+------------------+
| CURDATE( ) | @target | DAYNAME(@target) |
+------------+------------+------------------+
| 2002-07-15 | 2002-07-03 | Wednesday |
+------------+------------+------------------+


Some applications need to determine dates such as the
n-th instance of particular weekdays. For
example, if you administer a payroll where paydays are the 2nd and
4th Thursdays of each month, you'd need to know what
those dates are. One way to do this for any given month is to begin
with the first-of-month date and shift it forward.
It's easy enough to shift the date to the Thursday
in that week; the trick is to figure out how many weeks forward to
shift the result to reach the 2nd and 4th Thursdays. If the first of
the month occurs on any day from Sunday through Thursday, you shift
forward one week to reach the 2nd Thursday. If the first of the month
occurs on Friday or later, you shift forward by two weeks. The 4th
Thursday is of course two weeks after that.



The following Perl code implements this
logic to find all paydays in the year 2002. It runs a loop that
constructs the first-of-month date for the months of the year. For
each month, it issues a query that determines the dates of the 2nd
and 4th Thursdays:



my $year = 2002;
print "MM/CCYY 2nd Thursday 4th Thursday\n";
foreach my $month (1..12)
{
my $first = sprintf ("%04d-%02d-01", $year, $month);
my ($thu2, $thu4) = $dbh->selectrow_array (qq{
SELECT
DATE_ADD(
DATE_ADD(?,INTERVAL 5-DAYOFWEEK(?) DAY),
INTERVAL IF(DAYOFWEEK(?) <= 5, 7, 14) DAY),
DATE_ADD(
DATE_ADD(?,INTERVAL 5-DAYOFWEEK(?) DAY),
INTERVAL IF(DAYOFWEEK(?) <= 5, 21, 28) DAY)
}, undef, $first, $first, $first, $first, $first, $first);
printf "%02d/%04d %s %s\n", $month, $year, $thu2, $thu4;
}


The output from the program looks like this:



MM/CCYY   2nd Thursday   4th Thursday
01/2002 2002-01-10 2002-01-24
02/2002 2002-02-14 2002-02-28
03/2002 2002-03-14 2002-03-28
04/2002 2002-04-11 2002-04-25
05/2002 2002-05-09 2002-05-23
06/2002 2002-06-13 2002-06-27
07/2002 2002-07-11 2002-07-25
08/2002 2002-08-08 2002-08-22
09/2002 2002-09-12 2002-09-26
10/2002 2002-10-10 2002-10-24
11/2002 2002-11-14 2002-11-28
12/2002 2002-12-12 2002-12-26









    I l@ve RuBoard



    No comments:

    Post a Comment