Hallo iedereen,

In het maken van PHP-scripts ben ik een leek en probeer aldoende bij te leren. Voor onze sportvereniging onderhoud ik een website met daarop onderandere een agenda. Het eerste item op deze agenda is een maandelijkse bijeenkomst, telkens op de eerste woensdag van de maand, ongeacht of dit een feestdag is.

De originele Agenda is een html-pagina waar ik dan eenmaal per maand de data verander.

Daar er aan de website een database gekoppeld is, heb ik van deze pagina een PHP-paginaPHP-pagina gemaakt waar ik succesvol een script heb ingebracht (via een include()) om de namen te tonen van de leden die in de huidige maand verjaren.

Nu wou ik een tweede script toevoegen waarin de eerste woensdag van de huidige maand en de eerste woensdag van de volgende 5 maanden wordt weergegeven. Dat script is klaar en werkt naar behoren!



<?php
	
//lus om opeenvolgende maanden te bepalen

for ($i==0;$i<6;$i++){
	
// Voor de huidige maand, splits in 3 factoren
	
	if($i==0)
		{			
			$haaldatum = date('d-m-Y');
		$splitsdatum[$i] = explode('-',$haaldatum);



//$num bepaald op welke dag de eerste van de maand valt			

$num = date("w",mktime(0,0,0,$splitsdatum[$i][1],1,$splitsdatum[$i][2]));

// als de eerste van de maan een woensdag is, echo datum
	if($num==3){
		echo date("j F Y",mktime(0,0,0,$splitsdatum[$i][1],1,$splitsdatum[$i][2]))."<br/>";
		
// is de eerste van de maand geen woensdag maar groter, bereken de eerste woensdag vanaf 3de van de maand
	}elseif($num>3){
		echo date("j F Y",mktime(0,0,0,$splitsdatum[$i][1],3,$splitsdatum[$i][2])+(86400*(8-$num)))."<br/>";
		
//	is de eerste van de maand geen woensdag maar kleiner, bereken de eerste woensdag voor de 3de van de maand	
	}else{
		echo date("j F Y",mktime(0,0,0,$splitsdatum[$i][1],3,$splitsdatum[$i][2])+(86400*(1-$num)))."<br/>";
	}
// haal datum op voor de *i-de volgende maannd
		}else{
			$haaldatum = date('d-m-Y',strtotime('+'.$i.' months'));
			$splitsdatum[$i] = explode('-',$haaldatum);
			
			$num = date("w",mktime(0,0,0,$splitsdatum[$i][1],1,$splitsdatum[$i][2]));
// als de eerste van de maan een woensdag is, echo datum
	if($num==3){
		echo date("j F Y",mktime(0,0,0,$splitsdatum[$i][1],1,$splitsdatum[$i][2]))."<br/>";
// is de eerste van de maand geen woensdag maar groter, bereken de eerste woensdag vanaf 3de van de maand		
	}elseif($num>3){
		echo date("j F Y",mktime(0,0,0,$splitsdatum[$i][1],3,$splitsdatum[$i][2])+(86400*(8-$num)))."<br/>";
//	is de eerste van de maand geen woensdag maar kleiner, bereken de eerste woensdag voor de 3de van de maand	
	}else{
		echo date("j F Y",mktime(0,0,0,$splitsdatum[$i][1],3,$splitsdatum[$i][2])+(86400*(1-$num)))."<br/>";

		}
	
}
}
	?>


Als resultaat krijg ik dus telkens de datum van de eerste woensdag voor de huidige en 5 volgende maanden.

Als ik dit script nu kopieer en plak op de pagina agenda2.php krijg ik de echo's niet te zien.

Agenda bestaat uit een tabel en de code heb al op verschillende manieren ingevoerd (Copy/paste, include ()...

Ik krijg ook geen foutmelding en de pagina wordt gewoon opgebouwd.

Iemand enig idee waar dit fout gaat?
Nou, Ger heeft er veel meer kaas van gegeten dan ik hoor.
Echter, ben ik van mening dat in een database niet alleen dynamische gegevens staan, maar gewoon 'gegevens'.
En een datum is ook een gegeven iets.

Als ik de query iets optimaliseer krijg ik dit:
SELECT datum, DAYNAME(datum) 
FROM alle_data
WHERE datum >= NOW() 
AND DAYOFWEEK(datum) = 4
AND DAYOFMONTH(datum) BETWEEN 1 AND 7  
ORDER BY datum ASC
LIMIT 5


Mocht op jouw systeem de donderdag verschijnen, verander dan de 4 naar een 3.
Ik zou er nooit aan gedacht hebben en los het zo op in php, maar dit kan natuurlijk ook en ik vind t knap :)
Eddy,
De wortel van 666 is ook een gegegeven, maar je gaat toch geen tabel maken voor de uitkomsten van de wortel van 1 tot en met weet ik veel wat. Dit is logica die in de applicatie laag thuis hoort, zo ook voor een datum.

Overigens heb je gelijk met de dag van de week, ik was even in de war met PHP.

datum >= NOW() gaat nog steeds niet goed, al datum vandaag is wordt dit
2012-10-21 00:00:00 >= 2012-10-21 12:56:04
omdat je een datum met een datum tijd vergelijkt.

[size=xsmall]Toevoeging op 21/10/2012 14:21:11:[/size]

De PHP oplossing:[code]<?php
//$dayofweek 1 voor ma 7 voor zondag
function getAFirstDayOfMonths($dayofweek = 3, $range = 5, $dateformat = '%d-%m-%Y') {
$date = time();
$wd = date('N', $date);
//bepaal de eerste ?dag van de week
$someday = $date + (($dayofweek - $wd) * 86400);
//corrigeer als er een maand terug gegaan wordt
$someday += (date('m', $date) != date('m', $someday)) ? 7 * 86400: 0;
$dom = date('j', $someday);
//als de dag van de maand groter is dan 7 moeten we er een x aantal weken aftrekken
//en een coorectie uitvoeren op veelvouden van 7
$firstday = ($dom > 7) ? $someday - ((($dom % 7 == 0) ? -1 : 0) + floor($dom / 7)) * 7 * 86400 : $someday;
$maand = date('m', $firstday);
$firstdayS = array(strftime($dateformat, $firstday));
for ($i=1; $i<=$range;$i++) {
$dom = date('j', $firstday);
$year = date('Y');
//bepaal de laatse dag van de maand
if ($maand <= 7) {
//t/m juli hebben de oneven maanden 31 dagen
if($maand % 2 > 0) {
$ldom = 31;
}
else {
if($maand != 2) { //behalve feb
$ldom = 30;
}
else { //feb 28 behalve schrikkeljaren
$ldom = ($year % 4 != 0 || ($year % 100 == 0 && $year % 400 != 0)) ? 28 : 29;
}
}
}
else { //na juli de even maamden 31
$ldom = ($maand % 2 == 0) ? 31 : 30;
}
$weeks2add = ($ldom - $dom - 28 < 0) ? 4 : 5;
$firstday += $weeks2add * 7 * 86400;
$firstdayS[] = strftime($dateformat, $firstday);
$maand = date('m', $firstday);
}
return $firstdayS;
}
?>[code]
Werkt inderdaad ook!
Of het sneller is kan niet zo 1-2-3 zien, wel dat het een stukje geavanceerder is.
En wat een gedoe met het aantal dagen van de maand. Dat is toch ook vaststaand en niet zo ingewikkeld als regel 20 tm 37?
Wellicht een array met 30, 28, 30, 31, 30, 31, 30, 31, 31, 30, 31 beter?
Hi Eddy,
Als er geen schrikkeljaren bestaan had ik het misschien wel in een array gezet, maar ik ben sowieso niet van de hardcoding.
Ik heb even een test gedaan:
de functie: 0.00044798851013184
connect (lokale!)database en select database (nog geen query uitgevoerd!):0.013045072555542
een paar keer getest maar de functie blijft altijd sneller.

En een beetje zelfkritiek kan ook geen kwaad:
Waarom in hemelsnaam rekening houdem met eeuwen terwijl over 25 jaar deze functie niet meer zal werken


[size=xsmall]Toevoeging op 21/10/2012 15:10:28:[/size]

Speciaal voor jou:

SELECT
	CASE DAYOFWEEK(datum)
		WHEN 2 THEN 'Maandag'
		WHEN 3 THEN 'Dinsdag'
		WHEN 4 THEN 'Woensdag'
		WHEN 5 THEN 'Donderdag'
		WHEN 6 THEN 'Vrijdag'
		WHEN 7 THEN 'Zaterdag'
		ELSE 'Zondag'
	END AS dagnaam
FROM
	all_data
WHERE
	datum >= CURRENT_DATE();
LIMIT 7
Ger van Steenderen op 21/10/2012 15:00:19

Hi Eddy,
Als er geen schrikkeljaren bestaan had ik het misschien wel in een array gezet, maar ik ben sowieso niet van de hardcoding.


Is ook niet zo moeilijk:
<?php

function isLeap($year) {
if($year % 400 == 0)
return true;
else if($year % 100 == 0)
return false;
else if($year % 4 == 0)
return true;
return false;
}

?>

Groet, Frank

[size=xsmall]Toevoeging op 21/10/2012 17:26:16:[/size]

Wel grappig om te zien dat we allemaal een andere oplossing hebben voor hetzelfde probleem
Ik heb ook niet gezegd dat het moeilijk is:

$ldom = ($year % 4 != 0 || ($year % 100 == 0 && $year % 400 != 0)) ? 28 : 29;

Maar goed, zoals het nu voorstaat in PHP, haalt de functie jaar 2038 niet eens dus laat staan jaar 2100 (wat ik ik ook niet zal halen, dus boeien). En ik gebruik bewust geen datetime objecten omdat die geen locales ondersteunen.
Je functie is dan inderdaad een stuk sneller. En dus de moeite om te bewaren.
En helemaal met je eens: in 2025 zullen deze scripts ook niet meer nodig zijn, want dan is er wel iets beters/makkelijkers/handigers voor gevonden.

Reageren