Muse reader James asks:
If a person picks a date on a calendar, say the first Tuesday in a month, how do you calculate date of the first Tuesday in the next month and each succeeding month there after?
This is an immensely complicated issue that will take you days and weeks to sort out. What you need is to know the day number you are looking for (1=Sunday, 2=Monday, etc), The month number (where 1 = January, 2 = February etc.), and the year (where 2009 = 2009, 20010 = 20010 etc.). Then you need to download this handy function from cflib.org called FirstXDayOfMonth, written by a Mr. Troy Pullis. Pass in your values and it will give you back the first occurrence of that day in the month. Add 7 to it get the second occurrence, 14 to get the third etc. Here is an example:
The Third Thursday
For a lark we'll take the date "2/19/2009" - the third Thursday in February and see if we can't figure out the third Thursday in march and April. First, we need to get our 3 variables - month, day of the week and year.
<cfscript>
//The date to mirror.
dt = createDate(2009,2,19);
//next month
month = month(dateadd('m',1,dt));
year = year(dateadd('m',1,dt));
dayOfWk = dayofweek(dt);
</cfscript>
Ok.. that's given us the variables dayOfWk=5 (Thursday), year=2009, month=3 (March). Now to call our function:
<cfscript>
//The date to mirror.
dt = createDate(2009,2,19);
//next month
month = month(dateadd('m',1,dt));
year = year(dateadd('m',1,dt));
dayOfWk = dayofweek(dt);
// first thursday in march
firstDt = FirstXDayOfMonth(
//write it out for convenience
writeoutput(firstDt);
</cfscript>
Our call returns 3/5/2009. A quick gander at the calendar shows us that yes indeed, march 5th is the first Thursday in march. All we have left to do now is add 14 days to this date:
<cfscript>
thirdThur = dateadd('d',14,firstDt);
</cfscript>
This gives us the third Thursday of the month of March (or 3/19/2009). Of course you would need to wrap some logic around it if you are looking for a 5th occurrence - which is a possibility in every month except February.
Remember CFlib.org
One more note. Any time you have a question like this and you say to yourself "Self, surely you aren't the only one who's ever had this problem," then go take a peek at cflib.org or riaforge. Chances are you are right and someone has already solved your problem. In case you missed it, here is the code to the "firstXDayOfMonth" function.
<cfscript>
/**
* Returns a date object of the first occurrence of a specified day in the given month and year.
*
* @param day_number An integer in the range 1 - 7. 1=Sun, 2=Mon, 3=Tue, 4=Wed, 5=Thu, 6=Fri, 7=Sat. (Required)
* @param month_number Month value. (Required)
* @param year Year value. (Required)
* @return Returns a date object.
* @author Troy Pullis (tpullis@yahoo.com)
* @version 1, March 23, 2005
*/
function FirstXDayOfMonth(day_number,month_number,year) {
// date object of first day for given month/year
var start_of_month = CreateDate(year,month_number,1);
var daydiff = DayOfWeek(start_of_month) - day_number;
var return_date = "";
switch(daydiff) {
case "-1": return_date = DateAdd("d",1,start_of_month); break;
case "6": return_date = DateAdd("d",1,start_of_month); break;
case "-2": return_date = DateAdd("d",2,start_of_month); break;
case "5": return_date = DateAdd("d",2,start_of_month); break;
case "-3": return_date = DateAdd("d",3,start_of_month); break;
case "4": return_date = DateAdd("d",3,start_of_month); break;
case "-4": return_date = DateAdd("d",4,start_of_month); break;
case "3": return_date = DateAdd("d",4,start_of_month); break;
case "-5": return_date = DateAdd("d",5,start_of_month); break;
case "2": return_date = DateAdd("d",5,start_of_month); break;
case "-6": return_date = DateAdd("d",6,start_of_month); break;
case "1": return_date = DateAdd("d",6,start_of_month); break;
default: return_date = start_of_month; break;
// daydiff=0, default to first day in current month
} //end switch
return return_date;
}
</cfscript>