Page 1 of 1

Figure out Thurday meeting dates

Posted: Fri Aug 05, 2011 10:44 am
by Technocrat
So we have meetings every other Thursday and I would like to figure out the next three dates dates for them. I have the following code which works except it skips to the next Thursday if today is one of the meeting dates. So how can I keep it from skipping when it's Thursday? Is there a better code for this?

Code: Select all

function getMeeting($which_date) {
	//1294300800 Jan-6-2011
	$next = strtotime("next Thursday");
	$diff = round(($next - 1294300800) / 86400);
	if (($diff % 14) == 0) {
		$date = $next;
	} else {
		$date = strtotime("next Thursday", $next);
	}
	if $which_date == 0) {
		return date('l, F j, Y', $date);
	} else if ($which_date == 1) {
		$date = strtotime("+3 Thursday", $date);
		return date('l, F j, Y', $date);
	} else if ($which_date == 2) {
		$date = strtotime("+5 Thursday", $date);
		return date('l, F j, Y', $date);
	}
	return date('l, F j, Y', $date);
}

Re: Figure out Thurday meeting dates

Posted: Fri Aug 05, 2011 4:43 pm
by twinedev
A little different approach for ya:

Code: Select all

<?php

	function GetMeeting($whichWeek,$strFormat = 'l, F j, Y') {

		static $aryMeetings = array();

		$intNumMeetings = count($aryMeetings);

		if ($intNumMeetings == 0) {

			// First Time Call, build up an array of upcoming dates

			// BEGIN: CONFIGURATION - Adjust these as needed
				$intMeetingDayOfWeek = 4; // 0=Sun, 1=Mon, 2=Tues, 3=Wed, 4=Thur, 5=Fri, 6=Sat
				$intNumMeetings = 3;
				$intWeekOffset = 0; // Toggle this between 0 and 1 to find the correct set of weeks
			// END: CONFIGURATION - Adjust these as needed

			list($DayOfWeek,$intMonth,$intDay,$intYear) = explode("-",date('w-m-d-Y'));

			$tsToday = mktime(0,0,0,$intMonth,$intDay,$intYear);

			$intDayOffset = 60 * 60 * 25; // NOTE: 25 was used on purpose, see notes to why.

			if ($DayOfWeek <= $intMeetingDayOfWeek) {
				$intDaysTillThursday = ($intMeetingDayOfWeek-$DayOfWeek);
			}
			else {
				$intDaysTillThursday = ((7+$intMeetingDayOfWeek)-$DayOfWeek);
			}

			$tsThurday = $tsToday + $intDayOffset * $intDaysTillThursday;

			$WeekOfYear = date('W',$tsThurday);
			if ($WeekOfYear % 2 == $intWeekOffset) {
				// The meeting isn't this week, so skip to next week
				$tsThurday += $intDayOffset * 7;
			}

			// We have first Thursday to use, loop through
			for ($t = 0; $t < $intNumMeetings; $t++) {

				// Becasue offsets adds one hour, lets get it back to midnight of the date
				list($intMonth,$intDay,$intYear) = explode("-",date('m-d-Y',$tsThurday));
				$tsThurday = mktime(0,0,0,$intMonth,$intDay,$intYear);

				$aryMeetings[] = $tsThurday;

				$tsThurday += $intDayOffset * 14; // Advance to the next Thursday

			}
		}

		if ($whichWeek < $intNumMeetings) {
			return date($strFormat,$aryMeetings[$whichWeek]);
		}
		else {
			return '[ERR: Week Number out of Range]';
		}
	}
	// END: function GetMeeting($whichWeek,$strFormat = 'l, F j, Y')


// LETS TEST IT OUT!

for($t=0;$t<5;$t++) {
	echo $t,' = ',GetMeeting($t),"<br>\n";
}

?>
I broke it out a little more than if it was code I was using to make it a little more readable.

In the function, there are three lines that you need to adjust to configure when your meetings are. There are explained in the notes. The third one, leave alone at first, if you are geting the wrong weeks, change it to a 1

You may notice that in the code, to calculate a full day, I'm using 25 hours instead of 24. This was done on purpose to handle if the ending of Daylight Savings Time occurs sometime between now and end of the list of meetings (that day there is actually 25 hours that day if the timezone of the server is set to recognizes them). Since we don't care what hour of the day it is, technically if you add 5 days, to Midnight, August 8, 2011, you would get 5:00am, August 13, 2011, the code will round it back to midnight for ya. (This trick is safe, as long as you are never adding more than 22 days before rounding back to midnight (entering Daylight Savings time technically has just 23 hours that day).

To see an example of what I mean by the above, try changing it back to 24, and then adjust number of weeks to calculate (and display) to be 26 (to get a years worth) you would see something like this:

[text]4 = Thursday, October 13, 2011
5 = Thursday, October 27, 2011
6 = Wednesday, November 9, 2011
7 = Wednesday, November 23, 2011[/text]

This is because only using 24 hours a day, when it went to calculate Thursday, Nov 10, you actually ended up with 11:00pm, Wed, Nov 9th, which is obviously not a Thursday. Using the 25 hours for offset gets you 7:00am, Thurs, Nov 10th, which is the correct date. (and time gets reset back to midnight before being stored and using during next run through loop.)

I prefer this method over other functions, as there is less for for it to do when you are just working with integers instead of code that had to figure out what "next Thursday" means. As long as it is coded solid, works just fine.

-Greg

Re: Figure out Thurday meeting dates

Posted: Mon Aug 08, 2011 11:17 am
by Technocrat
Perfect! Thanks so much

Re: Figure out Thurday meeting dates

Posted: Mon Aug 08, 2011 12:54 pm
by califdon
@twinedev: Excellent algorithm and explanation! I have written several 'regular schedule' algorithms somewhat like this, but yours handles exceptions more reliably than mine. Thanks.

Re: Figure out Thurday meeting dates

Posted: Mon Aug 08, 2011 3:34 pm
by twinedev
Glad to help, I love to figure things like that out :-)

Re: Figure out Thurday meeting dates

Posted: Mon Aug 08, 2011 4:13 pm
by pickle
~twinedev's solution seems much more complex than necessary, to do something strtotime() should do for you automatically

I'm assuming $which_date can have a value of 0,1,2 if you want to return the next meeting, the one after that, or the one after that respectively.

Code: Select all

function getMeeting($which, $format = 'l, F j, Y')
{	
	# if today is Thursday
	$next = (date('N') == 4)
		# Start from today's date
		? time()
		# Otherwise start from the next Thursday
		: strtotime('next Thursday');
	
	# Add however many weeks is necessary (including 0)
	$date = strtotime('+'.$which.' week',$next);
	
	# Format & return
	return date($format,$date);
}

Re: Figure out Thurday meeting dates

Posted: Mon Aug 08, 2011 4:23 pm
by twinedev
Mine came from scheduling code that was designed to keep repeating, so I just grabbed and modified it to fit the function, but I agree Pickle's code is much simpler!

-Greg

Re: Figure out Thurday meeting dates

Posted: Mon Aug 08, 2011 4:26 pm
by pickle
Ah - that makes sense.

Re: Figure out Thurday meeting dates

Posted: Mon Aug 08, 2011 4:28 pm
by Technocrat
Problem is I don't just need to know the Thursdays I need to every other Thursday. So Pickle's code doesn't take that into account.

Re: Figure out Thurday meeting dates

Posted: Mon Aug 08, 2011 4:31 pm
by pickle
So multiply by 2:

Code: Select all

function getMeeting($which, $format = 'l, F j, Y')
{      
        # if today is Thursday
        $next = (date('N') == 4)
                # Start from today's date
                ? time()
                # Otherwise start from the next Thursday
                : strtotime('next Thursday');
       
        # Add however many weeks is necessary (including 0)
        $date = strtotime('+'.($which*2).' week',$next);
       
        # Format & return
        return date($format,$date);
}

Re: Figure out Thurday meeting dates

Posted: Mon Aug 08, 2011 4:33 pm
by califdon
Technocrat wrote:Problem is I don't just need to know the Thursdays I need to every other Thursday. So Pickle's code doesn't take that into account.
Actually it will if you slightly modify it to say "+2 week" instead of "week". Check out http://stringtotime.com/

Re: Figure out Thurday meeting dates

Posted: Mon Aug 08, 2011 9:52 pm
by McInfo
I think the best performance can be achieved by picking dates out of a hard-coded array. Problems are: it can make your code look bloated; it will continue to work only if you update the code every few years; and if you include too many dates, the advantage is lost (but is your code really going to survive until 2038?).

Re: Figure out Thurday meeting dates

Posted: Mon Aug 08, 2011 10:24 pm
by califdon
McInfo wrote:I think the best performance can be achieved by picking dates out of a hard-coded array. Problems are: it can make your code look bloated; it will continue to work only if you update the code every few years; and if you include too many dates, the advantage is lost (but is your code really going to survive until 2038?).
No doubt that's technically true, but I think the performance gain would be unmeasurable in a practical situation. I would probably use strtotime(), as Pickle suggested.

Re: Figure out Thurday meeting dates

Posted: Tue Aug 09, 2011 12:09 am
by McInfo
califdon wrote:No doubt that's technically true, but I think the performance gain would be unmeasurable in a practical situation. I would probably use strtotime(), as Pickle suggested.
My first instinct is to use strtotime(), too. I was just throwing the caching idea out there. This is an interesting problem and I've spent a lot of time (probably too much) investigating different strategies.

Re: Figure out Thurday meeting dates

Posted: Tue Aug 09, 2011 11:49 am
by califdon
McInfo wrote:My first instinct is to use strtotime(), too. I was just throwing the caching idea out there. This is an interesting problem and I've spent a lot of time (probably too much) investigating different strategies.
I know how you feel! :wink: