Link to home
Start Free TrialLog in
Avatar of rruth
rruth

asked on

Detect 3rd Tuesday of Month

Experts,

I need to dynamically display the numeric day of the 3rd Tuesday of every month on a web site. Unfortunately the 3rd Tuesday very rarely falls on the same numerical day. I will use this calulation to dynamically display the date of a club's next meeting that meets on the third Tuesday of every month. Any clues on how to do this would be very appreciated.

Thank you in advance!
Avatar of mkishline
mkishline

If you just want to display the next meeting (meaning only one meeting in advance):

<cfset curMonth = CreateDate(Year(Now()),Month(Now()),1) />
<cfset tuesday = "" />
<cfloop condition="NOT isDate(tuesday)">
      <cfloop index="i" from="0" to="6">
            <cfif DayOfWeek(DateAdd('d',i,curMonth)) EQ 3>
                  <cfset tuesday = DateAdd('d',i,curMonth) />
                  <cfset third_tuesday = DateAdd('ww',2,tuesday) />
                  <cfoutput>#DateFormat(third_tuesday,"mm/dd/yyyy")#</cfoutput>
                  <cfbreak />
            </cfif>
      </cfloop>
      <cfset curMonth = DateAdd('m',1,curMonth) />
</cfloop>
ASKER CERTIFIED SOLUTION
Avatar of js_vaughan
js_vaughan

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of dgrafx

Declare @cd datetime, @Tue3 datetime
Set @cd = '1/may/2006'
Set @Tue3 = DATEADD(wk,2, case when DatePart(dd,DATEADD(dd, 1, DATEADD(wk, DATEDIFF(wk,0, dateadd(dd,6-datepart(day,@cd),@cd)  ), 0))) > 7 then DATEADD(dd, -6, DATEADD(wk, DATEDIFF(wk,0, dateadd(dd,6-datepart(day,@cd),@cd)  ), 0)) else DATEADD(dd, 1, DATEADD(wk, DATEDIFF(wk,0, dateadd(dd,6-datepart(day,@cd),@cd)  ), 0)) end )
Select @Tue3 as T3

T3 from this query will give the 3rd Tuesday for whatever month you put into it.
In this ex you see Set @cd = '1/may/2006' - just change for whatever month you want the info on

This code is for sql server - have not tested on other dbs
Avatar of rruth

ASKER

That is wonderful, works perfect. Is it possible I could get you to explain the loops line by line so I can understand the logic behind the code?

Thank you very much!!!
Avatar of rruth

ASKER

js_vaughan

That's it, exactly what I needed. Could I get you to explain the code below line by line so I can understand the logic?

Thank you very much!!!

  <cfloop from="15" to="21" index="i">
    <cfset dateToCheck = CreateDate(Year(inputstream),Month(inputstream),i)>
    <cfif DayOfWeek(dateToCheck) EQ 3>
      <cfset result = dateToCheck>
    </cfif>
  </cfloop>
  <cfif DateFormat(result) LT DateFormat(now())>
    <cfset result = getTuesday(DateAdd('m',1,result))>
  </cfif>
<cfset curMonth = CreateDate(Year(Now()),Month(Now()),1) />
<cfset tuesday = "" />
<!--- While we have not found a date for tuesday --->
<cfloop condition="NOT isDate(tuesday)">
     <!--- Loop through the first seven days of the first week (where we know there has to be a tuesday) --->
     <cfloop index="i" from="0" to="6">
          <!--- If the day we're at is the third day of the week (tuesday) --->
          <cfif DayOfWeek(DateAdd('d',i,curMonth)) EQ 3>
               <!--- We've found the first tuesday --->
               <cfset tuesday = DateAdd('d',i,curMonth) />
               <!--- By adding two weeks, we'll find the third tuesday --->
               <cfset third_tuesday = DateAdd('ww',2,tuesday) />
               <!--- If the third tuesday is already passed, remove the date from tuesday and go to the next month --->
               <cfif DateCompare(third_tuesday,Now()) LTE 0>
                 <cfset tuesday = "" />
               <cfelse>
                 <!--- Output the date for the third tuesday --->
                 <cfoutput>#DateFormat(third_tuesday,"mm/dd/yyyy")#</cfoutput>
               </cfif>
               <cfbreak />
          </cfif>
     </cfloop>
     <!--- If we didn't find the third tuesday, look at the next month --->
     <cfset curMonth = DateAdd('m',1,curMonth) />
</cfloop>
So I guess you're not using Sql Server?
The post I made really is an excellent solution if you try it. :)

Not saying the others are bad or anything though ...
Sure thing.

<cfloop from="15" to="21" index="i">
- I looped between the 15th and 21st because the first 14 days of a month will have the first 2 occurances of any day, be it monday, tuesday, or saturday.

<cfset dateToCheck = CreateDate(Year(inputstream),Month(inputstream),i)>
- I used that day (between 15 and 21) and put into into the current month and year to create a real date

<cfif DayOfWeek(dateToCheck) EQ 3>
- The DayOfWeek will return a 1-7 depending on the day you are looking for.  Sunday starts at 1, so Tuesday is 3

<cfset result = dateToCheck>
- Once it is found, I save it

<cfif DateFormat(result) LT DateFormat(now())>
- This uses the DateFormat() to wrap the result you just got, and the current date to compare them on equal grounds (cuts off the time of day)

<cfset result = getTuesday(DateAdd('m',1,result))>
- If the result you found was before todays date, then it uses DateAdd to add a month to the result, then restarts the process all over again by calling the function itself
Avatar of rruth

ASKER

js_vaughan,

Ok, I'm almost there. Could you explain the argument "inputstream" and how its used? It looks like it has no value, yet it is being used to set the value of the var dateToCheck.

Thanks again!
Inputstream is just a generic term I always use with functions.  For me, "Inputstream" is what is coming into the function.. and "result" is what it sends back out.  These are really no different than variable names.

You can see my first call to the function was here at the bottom:

#getTuesday(Now())#
- That passed Now() to the function

<cfargument name="inputstream" type="any" required="yes">
- Inside the function, it assigns a name to what is being received.  For me, I just call it inputstream.

So the important part is just that you use <cfargument> to capture what is coming into the function.  "inputstream" is just a variable name