Php Puzzle - forthcoming dates

Hi

Currently I need to login into my website every month and update the date of the next event - the third saturday of every month.

There must be a way for php to help me do this less often.

I thought the smplest way would be for me to create an array of dates over the next 12 months: ie

(17th March, 21st April, 19th May… and so on)


       //dates
       $dates = array('17/03/2012', '21/04/2012', '19/05/2012');

        //SET CURRENT DATE
		$today = date("d.m.y");

And then pick from the array the first date which is greater than the current date.

But I’m not sure how I would do that?

Any help appreciated.

Thanks

Each 3rd Saturday for the year 2012.


// Get current time
$dt = time();
$count=0;
while(date("Y", $dt)==2012){
     // go to next months first date
     $dt = mktime(date("H", $dt), date("i", $dt), date("s", $dt), date("n", $dt)+1, 1);
     // forward 3 Satardays
     $dt = strtotime("+3 Saturday", $dt);
     echo date(DATE_RSS, $dt). "\
";
}

To know more about the mktime hacks. See interate-through-each-valid-calendar-days/

thanks - thats useful - it does give me the dates until Jan 2013 which stops me having to look in my diary!

I’m not sure how I then pick out the ‘next’ one.

Also what controls how far into the future it goes … i.e. why does it go to Jan 2013 and not stop at the end of 2012 - or for that matter go to feb 16th 2013 as that would be a full 12 months? And does it ‘move forward’ automatically as the current date progresses?

is it this?

while(date("Y", $dt)==2012)

Thanks

It was showing Date from Jan 2013 because of simple bug. I fixed it. See the new code.

// initialize date to current date
$dt = time();
while(true){
// go to next months first date
$dt = mktime(date("H", $dt), date("i", $dt), date("s", $dt), date("n", $dt)+1, 1);
$dt = strtotime("+3 Saturday", $dt);
if(date("Y", $dt) == 2013)
        break;
echo date(DATE_RSS, $dt). "\
";
};

If you want to get next 12 months date then count a variable in the loop. When it reaches to 12 break loop.

Yes, It moves forward automatically. I initialize the date to current date. This is the starting point. You can choose your starting point.

Currently I need to login into my website every month and update the date of the next event - the third saturday of every month.

Do you mean the last Saturday of the month though?

Like March July and September this year, where there are 5 Saturdays… :wink:

Thanks again. you are very generous.

Thanks too cups - but no - its the 3rd saturday not the last (phew).

That works a little better for me - I have ‘some’ more control.
See below for my updated version of your script.

It works fine until I request the 12th month from now - then it returns this year’s ‘12 month date’ not next years 12 month date (-ie 18th Feb 2012 not 16th Feb 2013). Not sure why… :blush:

// initialize date to current date
$dt = time();
$monthcount=0;  //pd start a month count at zero
$tdcount=0; //pd start a table cell count at zero
while(true){
// go to next months first date
$dt = mktime(date("H", $dt), date("i", $dt), date("s", $dt), date("n", $dt)+1, 1);
$dt = strtotime("+3 Saturday", $dt);
++$monthcount; //pd add 1 to the month count
++$tdcount; //pd add 1 to the table cell count

if ($monthcount >= 13) //stop getting the dates after 12 months
      break;
//echo $monthcount; //pd print month count for checking purposes
if ($tdcount > 6) { //if the number of dates is greater than 12 insert a new table row
echo "</tr><tr>";
$tdcount=0;//reset the table cell count
}
//echo date(DATE_RSS, $dt). "\
";
     echo  "<td>" . date("d-F y", $dt). "</td>";
};



it outputs this

<td>17-March 12</td><td>21-April 12</td><td>19-May 12</td><td>16-June 12</td><td>21-July 12</td><td>18-August 12</td></tr><tr><td>22-September 12</td><td>20-October 12</td><td>17-November 12</td><td>22-December 12</td><td>19-January 13</td><td>18-February 12</td>

Thanks again

Most of the problem with that code is it’s only incrementing the month… and ONLY the month, so it can’t roll over the date properly. The answer is to leverage strtotime’s text parsing TWICE… once for “third saturday of this month” and once for “next month” after… It might also be helpful to add a trap so that a date from this month isn’t added to the list, and I’m gonna wrap it in a function here so you can pass a request for any number of months returned as an array.


<?php

function getThirdSaturdays($months) {
	$baseStamp=$now=time();
	$result=array();
	while ($months>0) {
		$baseStamp=strtotime('third saturday of this month',$baseStamp);
		if ($baseStamp>$now) {
			$result[]=$baseStamp;
			$months--;
		}
		$baseStamp=strtotime('next month',$baseStamp);
	}
	return $result;
}

echo '
	<ul>';
$thirdSaturdayList=getThirdSaturdays(36); // three YEARS to test rollover
foreach ($thirdSaturdayList as $thirdSaturday) {
	echo '
		<li>',date('j F Y',$thirdSaturday),'</li>';
}
echo '
	</ul>';

?>

Should work on everything right up to the unix gateway of 2038… and past that if you’re on a system upgraded to do time as 64 bit instead of 32.

Oh, and you might not really need an array… ‘third saturday of +3 months’…


for ($t=0; $t<36; $t++) {
	echo '
		<li>',date('j F Y',strtotime('third saturday of +'.$t.' months')),'</li>';
}

Though that would lack the ‘is the current month already past’ check… a simple function could add that though…


<?php

function getThirdSaturdayPlusMonths($months) {
	$baseStamp=strtotime('third saturday of this month');
	if ($baseStamp<time()) $baseStamp=strtotime('next month');
	return strtotime('third saturday of +'.$months.' months',$baseStamp);
}
	
echo '
	<ul>';
for ($t=0; $t<36; $t++) echo '
		<li>',date('j F Y',getThirdSaturdayPlusMonths($t)),'</li>';
echo '
	</ul>';

?>

That way you aren’t filling memory up with an array you don’t need.

Just thought about it, lets get that if statement out of the loop.


function getThirdSaturdays($months) {
	$baseStamp=(
		strtotime('third saturday of this month')>time() ?
		time() :
		strtotime('last month')
	);
	$result=array();
	while ($months-- >0) {
		$result[]=($baseStamp=strtotime('third saturday of next month',$baseStamp));
	}
	return $result;
} 

programming 101, anything you can figure out before the loop, should go before the loop instead of inside it.

thanks deathshadow60

could you paste your solution in its its beautiful entirety. I can’t seem to get the workings to… work. :frowning:

Seems to work fine in my tests… cut/paste issue maybe?

I did up a quick demo page showing it in action:
http://www.cutcodedown.com/for_others/rooftop/thirdSaturdays.php

and I put a phps in place set to download (instead of view online) so you can grab it directly.
http://www.cutcodedown.com/for_others/rooftop/thirdSaturdays.phps

Hopefully that will get you up and running with it.

Hi

Thanks for going to so much trouble.

I can see yours works perfectly but I’ve copied and pasted from thirdSaturdays.phps and I get a set of dates all reading
1 January 1970. I wonder if my server is failing to pick up the server time / date in the first instance.

http://tinyurl.com/75jodxo

I have

function getThirdSaturdays($months) {
	$baseStamp=(
		strtotime('third saturday of this month')>time() ?
		time() :
		strtotime('last month')
	);
	$result=array();
	while ($months-- >0) {
		$result[]=($baseStamp=strtotime('third saturday of next month',$baseStamp));
	}
	return $result;
}

function getThirdSaturdayPlusMonths($months) {
	$baseStamp=strtotime('third saturday of this month');
	if ($baseStamp>time()) $baseStamp=strtotime('next month');
	return strtotime('third saturday of +'.$months.' months',$baseStamp);
}

echo '
	<div style="width:12em; float:left;">
		<h2>Array Test</h2>
		<ul>';
		
$thirdSaturdayList=getThirdSaturdays(36);
foreach ($thirdSaturdayList as $thirdSaturday) {
	echo '
			<li>',date('j F Y',$thirdSaturday),'</li>';
}

echo '
		</ul>
	</div>
	
	<div style="width:12em; float:left;">
		<h2>Procedural Test</h2>
		<ul>';
		
for ($t=0; $t<36; $t++) {
	echo '
			<li>',date('j F Y',getThirdSaturdayPlusMonths($t)),'</li>';
}

echo
		'</ul>
	</div>';
	

I would say your server time or strtotime function isn’t working properly.

What does a simple:

echo date(‘j F Y’),‘<br />’,date(‘j F Y’,strtotime(‘now’));

return for dates? If that’s saying the unix epoch (jan 1 '70) then something is indeed VERY wrong with your server or it’s PHP install.

Your test code looks fine.
http://tinyurl.com/75jodxo

It displays the correct date.