#native_company# #native_desc#
#native_cta#

Nth Weekday Of Every Month

By David Cloutman
on November 6, 2001

Version: 0.9

Type: Full Script

Category: Calendars/Dates

License: Other

Description: Essentially a timestamp that returns the date of the next nth weekday of a month. (E.g. the 4th Tuesday or the 1st Monday of every month. Many events are scheduled by this formula.) Allows for wide range of output formats using the same codes as date(). Written with organizations that have monthly meetings in mind, particularly non-profits. You may modify it to suit your own needs, however. Great for keeping time sensitive pages up to date.

<?php
/*
	(c) 2001 David Cloutman. (http://www.nokhawaga.com) This script may be freely distributed and modified to 
	individual needs. Please do not redistribute without giving credit.

	This script has only been briefly tested. It may contain undocumented code features. Use at your own
	risk. You may report problems to [email protected].

	The author offers no technical support for this script. No warranty is given or implied. Use at your
	own risk.

-----------------------------------------------------------------------------------------------------------

	nthDayOfMonth.inc.php v0.9
	
	Returns the date of next nth weekday of a month. For instance, the next 3rd Tuesday would be called as:
	
		nthDayOfMonth(3, 2);
	
	if you chose to use the default output strings. Other outputs can be specified by using the optional
	arguments.
	
	This string will only return dates within the current and next month. It is possible to specify dates
	such as the next fifth Monday that may not return a date within this period. If there is no valid date,
	the script will return the value of $noDateStr. You can modify the script if this does not suit your needs.
	
	$nthDay - and integer between 1 and 5 that specifies the week of the monthly event.
	$dayNum - 0 == Sunday ... 6 == Saturday
	$dateFormatStr - A string that controls the format of the scripts output. Uses same codes as date(). 
					 See PHP docs.
	$noDateStr - Only returned under special circumstances. What the script returns when a date requested
	             does not occur within the current or next month.
*/
function nthDayOfMonth ($nthDay, $dayNum, $dateFormatStr = "l, F j, Y", $meetsTodayStr = "Meets Today!", $noDateStr = "To Be Announced") {
	
	// Debugging feature: Prevents erroneous function calls.
	if ($nthDay > 5 || $nthDay < 1) { return "Not a valid date."; }
	if ($dayNum < 0 || $dayNum > 6) { return "Not a valid day."; }

	$thisMonth = date("n"); // [m]m
	$thisYear = date("Y"); // YYYY
	
	// This Month
	$lastDate = testMonth ($thisMonth, $thisYear, $nthDay, $dayNum);
	
	if (date("n/j/Y") == date("n/j/Y", $lastDate)) { return $meetsTodayStr; } // Returns Meets Today message event is today.
	
	// Next Month
	if (! $lastDate || $lastDate < time()) {
		if ($thisMonth != 12) {
			$thisMonth++;
		}
		else {
			$thisMonth = 1;
			$thisYear++;
		}
		
		$lastDate = testMonth ($thisMonth, $thisYear, $nthDay, $dayNum);
		
	}

	if (! $lastDate) { return $noDateStr; } // If the day specified in the function call does not occur within the two months tested.
	else { return date($dateFormatStr, $lastDate); } // Otherwise, return the date of the next event.
}

// Modularizes the code. This function looks for a future date in the month specified. You can alter the functionality of this algorithm by manipulating the way this function is called in the main part of this script.
function testMonth ($thisMonth, $thisYear, $nthDay, $dayNum) {
	
	$daysOfWeekFound = 0;
	$dayOfMonth = 1;
	
	$daysInMonth = daysInMonth($thisMonth, $thisYear);
	
	while ($daysOfWeekFound < $nthDay && $dayOfMonth <= $daysInMonth) {
		
		$testDateStr = "$thisMonth/$dayOfMonth/$thisYear"; // String dd/mm/yyyy must be converted to timestamp.
		
		
		//Last date is a timestamp integer that contains the last date tested.
		$lastDate = strtotime($testDateStr);
		$lastDateArr = getdate($lastDate);
		
		if ($lastDateArr[wday] == $dayNum) { $daysOfWeekFound++; }
		
		$dayOfMonth++;
	
	}
	
	if ($daysOfWeekFound != $nthDay) { return false; }
	return $lastDate;
}

// How many days are in a given month.
function daysInMonth($month, $year) {
	$feb = daysInFeb($year);
	$daysInMonthsArr = array(31, $feb, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
	$monthIndex = $month -1;
	return $daysInMonthsArr[$monthIndex];
}

// Deals with the leap year issue.
// Not Y2.2k compliant.
function daysInFeb($year) {
	if (is_int($year / 4) && ($year != 1900 && $year != 2100) ) { return 29; }
	else { return 28; }
}


?>