Every Week has a Wednesday
By Steve Durette

A project came up a while back where we had to be able to dynamically determine the number of weeks in a month. At first we decided to loop through all of the days of the month and count the number of weeks. As I was looking at the code, I thought that it seemed really inefficient.

At that time I happened to look over at a year at a glance calendar that I have sitting on my desk. This calendar had a listing of the number of weeks for each month. Two things hit me while looking at it. First, "Every Week has a Wednesday", now I know you might be thinking "well, duhhh", but on the calendar if a number of days was to be considered a week it had to have a Wednesday. For example, if the first of the month happened to fall on a Thursday, then that week would actually fall into previous month. The second thing that stuck out was that every month has at least 4 weeks. This suddenly seemed like more of a math problem than a looping problem.

This tutorial will show a mathematical way to deal with this problem and how to create a function to do all the work. This function will be written within cfscript tags to ensure that it will work with CF 5, MX, and MX 6.1.

So, first we start the function. (Comments will be included in the code to describe what is being done.)

A cfscript function in ColdFusion is created by first opening a cfscript tag and then the keyword function followed by the function name a (, a list of required attributes and a ). Then the function code itself will be enclosed in {}. Here is an example:

     function numWeeksInMonth(chkDate){           //The code goes here      }

The function above doesn?t actually do anything yet, but it does show how to set up the function. A few points of interest? If you noticed our required parameter chkDate was included inside the (). If there weren?t any REQUIRED arguments, then the chkDate could have been left out and just () put there instead. I.e. function numWeeksInMonth()

Just because you didn?t put anything (or a limited number of things) in between the parenthesis doesn?t mean that you can?t accept input into the function. Anything passed in will still be available through an array called Arguments. So if you wanted to see what was passed in, you could loop through the Arguments array.

Enough of that for now, for this function, we will not be using the arguments array but a required variable which will hold a date.

Normally, I would take the time to do tests to make sure that the value passed was a date, but since this is actually a very simple function we will let ColdFusion deal with any problems that arise from passing things other than dates.

Now, back to our theory. Another look at the calendar produced more information. If the first Wednesday of the month we were checking had a date that was after the third, then there was no way that there could be 5 weeks because the last days of the month would fall before the Wednesday that would make it 5 weeks. I know it sounds strange, but look at a calendar and you will see it?s true. Take a look at August 2004 and you will see, the first Wednesday is the 4th and the 31st falls on a Tuesday stopping it from being a 5-week month. So, if the date of the first Wednesday is greater than 3 we know that there are only 4 weeks that will save us a lot of work. Next, if the first Wednesday is 3 or less we want to find out if the date of the Wednesday 4 weeks from now is in the same month. Wait a second, 4-week times 7 days is 28 days. All we have to do is add 28 days and see if the date is still in the same month. If not there are only 4 weeks.

On to another note about writing functions, if you want to use variables in your function and not have them persist after the function completes, they must be defined at the beginning of the function and must be preceded by the var command. Leaving off the var will cause the variables to be created in the Variables scope and therefore accessible to the page that calls the function. Now some of you may argue that you like the idea that the function manipulates variables outside of it and yes I believe that there may be a time and place for that, but for functions such as this, there is no need. When the function is done we don?t want the function variables sticking around.

Well enough of theory, here is the code.

    function numWeeksInMonth(chkDate) {         var retWeeks = 4;         var tempDate = createDate(year(chkDate), month(chkDate), "1");         /*  First we create the variables that will be used in the function. Since we know that a month must have at least 4 weeks in it we assume that there are 4 weeks. We also create a temporary date variable and populate it with the first date of the month of the date that was passed to the function.          */         /* Now we make sure that we point to Wednesday. This is because we have determined that Wednesdays are important to us. How this works is we are going to subtract (4 ? current day value) from tempDate. If the current day value is Wednesday (4) we do nothing otherwise we get a date that points to a Wednesday.          */          tempDate = dateAdd("d", (4 ? dayOfWeek(tempDate)), tempDate);          /* Now we test to see if this new Date is in the current month. If it weren?t, then it would be in the last week of the previous month. So we add 7 days to get to the first Wednesday of the month we are checking.          */          if(month(tempDate) neq month(chkDate)) tempDate = dateAdd("d", 7, tempDate);         /*          Now we look at something to determine whether or not we have 5 weeks in the month we are checking. If the first Wednesday of the month has a day greater than the 3rd then there can?t be 5 weeks. So, we only have to check for 5 weeks if the day of tempDate is 3 or less. If it is 3 or less, then we add 28 days to the tempDate and see if it is in the same month.         */          if(day(tempDate) lte 3 and month(dateAdd("d", 28, tempDate)) is month(chkDate))           //Since we passed all of the tests, set the number of weeks to 5.           retWeek = 5;          //Finally, we return the number of weeks based on our tests.           return retWeeks;      }

You might have noticed that we used a new command at the end of the function. In order to get the results out, we have to use the return command. It simply lets you tell the function what to return. We could have just as easily hard coded something there like return 1;, but what would be the use of a function that always returns the same thing?

Now, why don?t we use this new function. In order to display it we need to put the function in with a little more cfml code.

    function numWeeksInMonth(chkDate) {          var retWeeks = 4;          var tempDate = createDate(year(chkDate), month(chkDate), "1");          tempDate = dateAdd("d", (4 ? dayOfWeek(tempDate)), tempDate);          if(month(tempDate) neq month(chkDate))                  tempDate = dateAdd("d", 7, tempDate);          if(day(tempDate) lte 3 and month(dateAdd("d", 28, tempDate)) is month(chkDate))                  retWeek = 5;          return retWeeks;    }        Test the new function.       The number of weeks in this month is: #numWeeksInMonth(now())#

Save this cfml file (I used the name funcTest.cfm) and run it. For December 2003 it returned:

Well, that completes our function and this tutorial. I hope it helped you with understanding how to create and use functions and hopefully the function will help you in your quest for the number of weeks in a month.

For those who would like to see this function in action, you can go to http://www.durette.org and choose tutorials for a menu of available tutorial demos.

Author: Steven Durette
Skill Level: Beginner

Platforms Tested: CF5,CFMX
Total Views: 85,741
Submission Date: December 24, 2003
Last Update Date: June 05, 2009
All Tutorials By This Autor: 4
Discuss This Tutorial
• Great work. Looks like small piece of code but very strong, logical and helpful. Keep the good thing on man. It really helped me. Thanks again

• i want the derw that will come out next week,i want it three day from now.