Search Box for next occurance date

Hi,
I’m developing a calendar that is designed to show all the jobs scheduled for my company.
I’ve been working on creating a text field that lets a user enter the address, job type and/or date into this field and using jquery’s autocomplete it will show a list which when an item is clicked on will take the user to the next occurrence of that job.

My problem is that while constructing the date for the next occurrence with PHP for some reason a large portion of events repeated on a 4 weekly basis that are not on Monday seem to generate the date of the day before they are actually on, but when clicked on it will open the correct event on the correct day.

Below is the PHP loadSearchItems.php File (bug in the date creation used for $html, the filtering of duplicates works as expected)

<?php
	//Used to filter duplicates out
	//Gets the next future occurrence
	//params:
	//		- $start : The start date
	//		- $rec   : The recurring type
	//					$type_$interval_$day_$interval2_$days#extra
	function getNextDate($start, $rec) {
		$serviceDate = mysql_escape_string($start);
		$rec_type = mysql_escape_string($rec);
		
		$s = explode('-', $serviceDate);
		$DAY = $s[2];
		$MONTH = $s[1];
		$YEAR = $s[0];
		$rec_type2 = explode("_", $rec_type);
		$type = $rec_type2[0];
		$interval = $rec_type2[1];
		$day = $rec_type2[2];
		$interval2 = $rec_type2[3];
		$days = $rec_type2[4];
		$days = explode("#", $days);
		$days = explode(",", $days[0]);
		$nextService = "1970-01-01 00:00:00";
		
		//Check what the recurrence type is
		if ($type == "day") {
			$nextService = date("Y-m-d H:i:s", (strtotime($serviceDate) + (86400 * $interval)));
		} else if ($type == "week") {
			$d = date("w", strtotime($serviceDate));
			if ($d == 0)
				$d = "sunday";
			else if ($d == 1)
				$d = "monday";
			else if ($d == 2)
				$d = "tuesday";
			else if ($d == 3)
				$d = "wednesday";
			else if ($d == 4)
				$d = "thursday";
			else if ($d == 5)
				$d = "friday";
			else if ($d == 6)
				$d = "saturday";
				
			$dt = strtotime("next $d", mktime(0, 0, 0, $MONTH, ($DAY + ($interval * 7) - 7), $YEAR));
			$nextService = date("Y-m-d H:i:s", $dt);
		} else if ($type == "month") {
			if ($day == "" && $interval2 == "") {
				$y = $YEAR;
				$m = $MONTH;
				$m = ($m + $interval);
				$yAdjust = floor(($m / 12));
				$y = ($y + $yAdjust);
				$mAdjust = $m % 12;
				if ($mAdjust == 0)
					$m = "12";
				else if ($mAdjust < 10)
					$m = "0".$m;
				$d = $DAY;
				$dt = $y."-".$m."-".$d;
				$nextService = date("Y-m-d H:i:s", strtotime($dt));
			} else {
				$y = $YEAR;
				$m = $MONTH;
				$m = ($m + $interval);
				if ($m > 12) {
					$yAdjust = floor(($m / 12));
					$y = ($y + $yAdjust);
					$m = ceil($m / 12);
					if ($m == 0)
					$m = "12";
					else if ($m < 10)
						$m = "0".$m;
				}
					
				$d = $day;
				if ($d == 0)
					$d = "sunday";
				else if ($d == 1)
					$d = "monday";
				else if ($d == 2)
					$d = "tuesday";
				else if ($d == 3)
					$d = "wednesday";
				else if ($d == 4)
					$d = "thursday";
				else if ($d == 5)
					$d = "friday";
				else if ($d == 6)
					$d = "saturday";
					
				$mW = $interval2;
				if ($mW == "1")
					$mW = 'first';
				else if ($mW == "2")
					$mW = 'second';
				else if ($mW == "3")
					$mW = 'third';
				else if ($mW == "4")
					$mW = 'fourth';
				else if ($mW == "5")
					$mW = 'fifth';
				
				$dt = strtotime("$mW $d", mktime(0, 0, 0, $m, 1, $y));
				$nextService = date("Y-m-d H:i:s", $dt);
			}
		} else if ($type == "year") {
			if ($day == "" && $interval2 == "") {
				$y = ($YEAR + $interval);
				$m = $MONTH;
				if ($m < 10)
					$m = "0".$m;
				$d = $DAY;
				if ($d < 10)
					$d = "0".$d;
				$dt = strtotime($y."-".$m."-".$d);
				$nextService = date("Y-m-d H:i:s", $dt);
			} else {
				$y = ($YEAR + $interval);
				
				$d = $day;
				if ($d == 0)
					$d = "sunday";
				else if ($d == 1)
					$d = "monday";
				else if ($d == 2)
					$d = "tuesday";
				else if ($d == 3)
					$d = "wednesday";
				else if ($d == 4)
					$d = "thursday";
				else if ($d == 5)
					$d = "friday";
				else if ($d == 6)
					$d = "saturday";
					
				$mW = $interval2;
				if ($mW == "1")
					$mW = 'first';
				else if ($mW == "2")
					$mW = 'second';
				else if ($mW == "3")
					$mW = 'third';
				else if ($mW == "4")
					$mW = 'fourth';
				else if ($mW == "5")
					$mW = 'fifth';
				
				$dt = strtotime("$mW $d", mktime(0, 0, 0, $m, 1, $y));
				$nextService = date("Y-m-d H:i:s", $dt);
			}
		}
		//While the next occurrence date is in the past find the next date
		while (strtotime($nextService) < strtotime(date("Y-m-d H:i:s"))) {
			$sD = explode(" ", $nextService);
			$sD = explode("-", $sD[0]);
			$YEAR = $sD[0];
			$MONTH = $sD[1];
			$DAY = $sD[2];
			
			if ($type == "day") {
				$nextService = date("Y-m-d H:i:s", (strtotime($nextService) + (86400 * $interval)));
			} else if ($type == "week") {
				$d = date("w", strtotime($nextService));
				if ($d == 0)
					$d = "sunday";
				else if ($d == 1)
					$d = "monday";
				else if ($d == 2)
					$d = "tuesday";
				else if ($d == 3)
					$d = "wednesday";
				else if ($d == 4)
					$d = "thursday";
				else if ($d == 5)
					$d = "friday";
				else if ($d == 6)
					$d = "saturday";
				
				$dt = strtotime("next $d", mktime(0, 0, 0, $MONTH, ($DAY + ($interval * 7) - 7), $YEAR));
				$nextService = date("Y-m-d H:i:s", $dt);
			} else if ($type == "month") {
				if ($day == "" && $interval2 == "") {
					$y = $YEAR;
					$m = $MONTH;
					$m = ($m + $interval);
					$yAdjust = floor(($m / 12));
					$y = ($y + $yAdjust);
					$mAdjust = $m % 12;
					if ($mAdjust == 0)
						$m = "12";
					else if ($mAdjust < 10)
						$m = "0".$m;
					$d = $DAY;
					$dt = $y."-".$m."-".$d;
					$nextService = date("Y-m-d H:i:s", strtotime($dt));
				} else {
					$y = $YEAR;
					$m = $MONTH;
					$m = ($m + $interval);
					if ($m > 12) {
						$yAdjust = floor(($m / 12));
						$y = ($y + $yAdjust);
						$m = ceil($m / 12);
						if ($m == 0)
						$m = "12";
						else if ($m < 10)
							$m = "0".$m;
					}
						
					$d = $day;
					if ($d == 0)
						$d = "sunday";
					else if ($d == 1)
						$d = "monday";
					else if ($d == 2)
						$d = "tuesday";
					else if ($d == 3)
						$d = "wednesday";
					else if ($d == 4)
						$d = "thursday";
					else if ($d == 5)
						$d = "friday";
					else if ($d == 6)
						$d = "saturday";
						
					$mW = $interval2;
					if ($mW == "1")
						$mW = 'first';
					else if ($mW == "2")
						$mW = 'second';
					else if ($mW == "3")
						$mW = 'third';
					else if ($mW == "4")
						$mW = 'fourth';
					else if ($mW == "5")
						$mW = 'fifth';
					
					$dt = strtotime("$mW $d", mktime(0, 0, 0, $m, 1, $y));
					$nextService = date("Y-m-d H:i:s", $dt);
				}
			} else if ($type == "year") {
				if ($day == "" && $interval2 == "") {
					$y = ($YEAR + $interval);
					$m = $MONTH;
					if ($m < 10)
						$m = "0".$m;
					$d = $DAY;
					if ($d < 10)
						$d = "0".$d;
					$dt = strtotime($y."-".$m."-".$d);
					$nextService = date("Y-m-d H:i:s", $dt);
				} else {
					$y = ($YEAR + $interval);
					
					$d = $day;
					if ($d == 0)
						$d = "sunday";
					else if ($d == 1)
						$d = "monday";
					else if ($d == 2)
						$d = "tuesday";
					else if ($d == 3)
						$d = "wednesday";
					else if ($d == 4)
						$d = "thursday";
					else if ($d == 5)
						$d = "friday";
					else if ($d == 6)
						$d = "saturday";
						
					$mW = $interval2;
					if ($mW == "1")
						$mW = 'first';
					else if ($mW == "2")
						$mW = 'second';
					else if ($mW == "3")
						$mW = 'third';
					else if ($mW == "4")
						$mW = 'fourth';
					else if ($mW == "5")
						$mW = 'fifth';
					
					$dt = strtotime("$mW $d", mktime(0, 0, 0, $m, 1, $y));
					$nextService = date("Y-m-d H:i:s", $dt);
				}
			}
		}
		return $nextService;
	}
	function checkDatesInArray($arrs = "", $item) {
		$items = array();
		for($i = 0; $i < count($arrs); $i++) {
			if (strtotime($arrs[$i][2]) > strtotime($item[2]) && $arrs[$i][4] == $item[4] && $arrs[$i][14] == $item[14]) {
				return $i;
			}
		}
		
		return count($arrs);
	}
	$html = "";
	$html .= "var addressList = [";
	 $con = calendar_dbOpen();
	 //Get the next occurrences for the series' that are in the future
	 $query = "SELECT event_pid, tasks_id FROM tasks WHERE abn = '$abn' AND event_pid != '0' AND end_date >= curdate()";
	 $result = mysql_query($query, $con);
	 $q = "";
	 if (mysql_num_rows($result) > 0) {
	 	while ($item = mysql_fetch_array($result))
	 		$q .= " OR tasks_id = '" . $item[0] . "' OR tasks_id = '" . $item[1] . "'";
	 }
	 $q = substr($q, 4);
	 //SELECT everything related to the task where the id's are of the previous search.
	 //tasks returned will be those of future occurrences and the series relating to those occurrences
	 $query = "SELECT * FROM tasks WHERE $q ORDER BY address ASC";
	 $result = mysql_query($query, $con);
	 $itemsExcluded = array();
	 if (mysql_num_rows($result) > 0) {
	 	$items = array();
	 	//Loop though all returned results
	 	while ($item = mysql_fetch_array($result)) {
	 		//if event_pid == 0, then check when it's next occurrence is and set that as the start date
	 		if ($item[6] == "0") {
		 		$item[2] = getNextDate($item[2], $item[5]);
		 	}
		 	$tasksIdList[] = $item[0];
		 	//Don't allow a series to be shown if an occurrence occurs on that day
		 	$newId = checkDatesInArray($items, $item);
		 	$itemsExcluded[] = $items[$newId][0];
		 	$items[$newId] = $item;
	 	}
	 }
	 $ii = 0;
	 while($ii < count($items)) {
	 	$newId = "N/A";
	 	for($i = 0; $i < count($items); $i++) {
	 		if ($items[$i][4] == $items[$ii][4] && $items[$i][14] == $items[$ii][14] && $i != $ii) {
	 			if (strtotime($items[$i][2]) > strtotime($items[$ii][2]))
	 				$newId = $i;
	 			else
	 				$newId = $ii;
	 			$i = count($items);
				$itemsExcluded[] = $items[$newId][0];
	 		}
	 	}
	 	$ii++;
	 }
	 	
	 //Get all the tasks details for the company and have not been excluded due to being duplicate events
	 $query = "SELECT address, service, event_length, start_date, end_date, rec_type, event_pid FROM tasks WHERE abn = '$abn'";
	 for($i = 0; $i < count($itemsExcluded); $i++)
	 	$query .= " AND tasks_id != '".$itemsExcluded[$i]."'";
	 $query .= " ORDER BY address";
	 $result = mysql_query($query, $con);
	 $items = array();
	 while ($item = mysql_fetch_array($result)) {	 				
	 	$items[] = $item;
	 }
	 //loop though all the results to find the next occurrence date
	 //Than store this date in $html along with the other data required for the autocomplete options
	 for($i = 0; $i < (mysql_num_rows($result) - 1); $i++) {
	 	$sDate = $items[$i][3];
	 	$eDate = $items[$i][4];
	 	//If occurrence
	 	if ($items[$i][6] != "0" && strtotime(date("Y-m-d H:i:s",strtotime($sDate))) > strtotime(date("Y-m-d H:i:s"))) {
	 		$sDate = explode(" ", $sDate);
	 		$sDate[0] = explode("-", $sDate[0]);
	 		$sDate[0] = $sDate[0][2] . "-" . $sDate[0][1] . "-" . $sDate[0][0];
	 		$sDate = implode(" ", $sDate);
	 		$sDate = strtotime($sDate);
	 		$sDate = date("d-m-Y", $sDate);
	 		$html .=  "{label:'" . $items[$i][0] . " (" . $items[$i][1] . ") [" . $sDate . "]', value:'" . $items[$i][0] . " (" . $items[$i][1] . ")'},\n";
	 	//If series
	 	} else if (strtotime($eDate) >= strtotime(date("Y-m-d H:i:s"))) {
	 		$recType = $items[$i][5];
	 		$recType = explode("#", $recType);
	 		$recType = explode("_", $recType[0]);
	 		$step = 0;
	 		$sDate = explode(" ", $sDate);
	 		$sDate[0] = explode("-", $sDate[0]);
	 		$sDate[0] = $sDate[0][2] . "-" . $sDate[0][1] . "-" . $sDate[0][0];
	 		$sDate = implode(" ", $sDate);
	 		$multiplier = 0;
	 		//Adjust the multiplier field for if the recurrence start date is a monday
	 		//Other days of the week seem to work fine without this
	 		if (date("D", strtotime($sDate)) == "Mon") {
	 			$multiplier = 86400;
	 		}
	 		$next = strtotime($sDate);
	 		$next = date("Y-m-d H:i:s", $next);
	 		$next = strtotime($next);
	 		if ($recType[0] == "day") {
	 			$step = 86400 * $recType[1];
	 			while($next <= strtotime(date("Y-m-d H:i:s")))
	 				$next += $step;
	 		} else if ($recType[0] == "week") {
	 			$days = explode(",", $recType[4]);
	 			$step = 604800 * $recType[1];
	 			$next2 = $next;
	 			$week = (86400 * 7 * $recType[1]) - 86400;
	 			$flag = false;
	 			while($next2 <= strtotime((date("Y-m-d H:i:s",(strtotime(date("Y-m-d H:i:s"))+$week)))) && !$flag) {
	 				if (count($days) > 1) {
	 					for($ii = 0; $ii < count($days); $ii++) {
	 						$day = $days[$ii];
	 						$next = $next2;
	 						$next += 86400 * ($days[$ii] - 1);
	 						if ($next > strtotime(date("Y-m-d H:i:s"))) {
	 							$ii = count($days);
	 							$flag = true;
	 						}
	 					}
	 				} else {
	 					$next = $next2;
	 					$next += ($multiplier * ($days[0] - 1));
	 					if ($next > strtotime(date("Y-m-d H:i:s"))) {
	 						$flag = true;
	 					}
	 				}
	 				$next2 += $step;
	 			}
	 			if ($flag == false) {
	 				for($ii = 0; $ii < count($days); $ii++) {
	 					$next = $next2;
	 					if ($next > strtotime(date("Y-m-d H:i:s"))) {
	 						$ii = count($days);
	 					}
	 				}
	 			}
	 		} 
	 		if ($recType[0] == "month" || $recType[0] == "year") {
	 			$html .=  "{label:'" . $items[$i][0] . " (" . $items[$i][1] . ")', value:'" . $items[$i][0] . " (" . $items[$i][1] . ")'},\n";
	 		} else {
					$html .=  "{label:'" . $items[$i][0] . " (" . $items[$i][1] . ") [" . date("d-m-Y", $next) . "]', value:'" . $items[$i][0] . " (" . $items[$i][1] . ")'},\n";
				}
			}
		}
		$i = (mysql_num_rows($result) - 1);
		if ($items[$i][6] != "0") {
			$sDate = explode(" ", $sDate);
			$sDate[0] = explode("-", $sDate[0]);
			$sDate = $sDate[0][2] . "-" . $sDate[0][1] . "-" . $sDate[0][0];
			//$sDate = implode(" ", $sDate);
	 		$sDate = strtotime($sDate);
	 		$sDate = date("d-m-Y", $sDate);
			$html .=  "{label:'" . $items[$i][0] . " (" . $items[$i][1] . ") [" . $sDate . "]', value:'" . $items[$i][0] . " (" . $items[$i][1] . ")'}\n";
		} else if (strtotime($eDate) >= strtotime(date("Y-m-d H:i:s"))) {
			$recType = $items[$i][5];
			$recType = explode("#", $recType);
			$recType = explode("_", $recType[0]);
			$step = 0;
			$sDate = explode(" ", $sDate);
			$sDate[0] = explode("-", $sDate[0]);
			$sDate[0] = $sDate[0][2] . "-" . $sDate[0][1] . "-" . $sDate[0][0];
			$sDate = implode(" ", $sDate);
			$multiplier = 0;
	 		//Adjust the multiplier field for if the recurrence start date is a monday
	 		//Other days of the week seem to work fine without this
			if (date("D", strtotime($sDate)) == "Mon") {
				$multiplier = 86400;
			}
			$next = strtotime($sDate);
			$next = date("Y-m-d", $next);
			$next = strtotime($next);
			if ($recType[0] == "day") {
				$step = 86400 * $recType[1];
				while($next <= strtotime(date("Y-m-d H:i:s"))) {
					$st = strtotime(date("Y-m-d H:i:s"));
					$next += $step;
				}
		} else if ($recType[0] == "week") {
			$days = explode(",", $recType[4]);
			$step = 604800 * $recType[1];
			$next2 = $next;
			$week = (86400 * 7 * $recType[1]) - 86400;
			$flag = false;
			while($next2 <= strtotime((date("Y-m-d H:i:s",(strtotime(date("Y-m-d H:i:s"))+$week)))) && !$flag) {
				if (count($days) > 1) {
					for($ii = 0; $ii < count($days); $ii++) {
						$day = $days[$ii];
						$next = $next2;
						$next += 86400 * ($days[$ii] - 1);
						if ($next > strtotime(date("Y-m-d H:i:s"))) {
							$ii = count($days);
							$flag = true;
						}
					}
				} else {
					$next = $next2;
					$next += ($multiplier * ($days[0] - 1));
					if ($next > strtotime(date("Y-m-d H:i:s"))) {
						$flag = true;
					}
				}
				$next2 += $step;
			}
			if ($flag == false) {
				for($ii = 0; $ii < count($days); $ii++) {
					$next = $next2;
					if ($next > strtotime(date("Y-m-d H:i:s"))) {
						$ii = count($days);
					}
				}
			}
		}
		if ($recType[0] == "month" || $recType[0] == "year") {
			$html .=  "{label:'" . $items[$i][0] . " (" . $items[$i][1] . ")', value:'" . $items[$i][0] . " (" . $items[$i][1] . ")'}\n";
		} else {
			$html .=  "{label:'" . $items[$i][0] . " (" . $items[$i][1] . ") [" . date("d-m-Y", $next) . "]', value:'" . $items[$i][0] . " (" . $items[$i][1] . ")'}\n";
		}
	}
	my_dbClose($con);
	$html .= "];";
	//Prints the variable addressList to the page to be used in jquery's autocomplete field
	echo $html;
?>

and the Jquery autocomplete function (which works)

$(function() {
	 	<?php include "loadSearchItems.php"; ?>
		$("#address").autocomplete({
			source: addressList,
			close: function(event, ui) {
				//Get the value entered in the search box
				var d = {"address":$("#address").val()};
				if ($("#address").val() != "") {
					$.ajax({
						url: "loadAddressId.php",
 				 		type: "POST",
 				 		async: false,
 				 		dataType: "text",
 				 		data: d,
 				 		success: function(data) {
 				 			//data = the id of the series within the database
 				 			var id = data;
 				 			if (id > 0) {
								var rcd = scheduler.getRecDates(id);
								var d = new Date();
								//loop through all recDates
								for(var i = 0; i < rcd.length; i++) {
									//if the recDate is in the future
									if (rcd[i].start_date.getTime() >= d) {
										var m = scheduler.getState().mode;
										scheduler.init('scheduler_here',rcd[i].start_date,m);
										//Grab the events details
										var evs = scheduler.getEvents(rcd[i].start_date,rcd[i].end_date);
										var flag = false;
										//Handle multiple events at the same time
										for (var i=0; i<evs.length; i++) {
											var str = evs[i].id;
											str = str.split("#");
											//Check to see if the id matches either the occurrence's id or the parent's id
											if (str[0] == id || id == evs[i].event_pid) {
											    id = evs[i].id;
											    flag = true;
											    i = evs.length;
											}
										}
										i = rcd.length;
									}
								}
								<?php
								if ($searchOption == "skip") {
									echo "scheduler.showEvent(id, scheduler.getState().mode);\n";
								} else if ($searchOption == "skipOpen") {
									echo "scheduler.showEvent(id, scheduler.getState().mode);\n";
									echo "scheduler.showLightbox(id);\n";
								} else {
									echo "scheduler.showLightbox(id);\n";
								}
								?>
							}
 				 		}
					});
				}
			}
		})
	});

and just to be complete the loadAddressId.php

<?php
	session_start();
	include "../includes/defs.php";
	
	$text = mysql_escape_string($_POST['address']);
	
	$address = substr($text, 0, strrpos($text, " ("));
	$service = substr($text, strrpos($text, "(")+1, strlen($text)-strrpos($text, "("));
	$service = substr($service, 0, strrpos($service, ")"));
	
	$con = calendar_dbOpen();
	$query = "SELECT tasks_id FROM tasks WHERE address = '$address' AND service = '$service'";
	$result = mysql_query($query, $con);
	$items = array();
	while ($item = mysql_fetch_array($result)) {
		$items[] = $item[0];
	}
	if (mysql_num_rows($result) > 0) {
		$html = $items[0];
	}
	my_dbClose($con);
	echo $html;	
?>

Any advice about how to fix the date bug in the php for the autocomplete menu would be much appreciated, it’s starting to drive me mad, I’ve spent so much time on it

Hi,
here is a demo which provides class for calculating all occurences for required recurring event id.
Have a look at file get_events.php, it shows how to use it.
scheduler-helper.zip (2.66 KB)