Aantal dagen bereken mbv diff()
Ik zit weer eens met een vraagstuk... ik wil het aantal dagen bereken tussen twee datums..
daarvoor dacht ik onderstaand stukje codering te kunnen gebruiken:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
//* RECONCILATION INSTELLINGEN
$originalReconcileDate = $sqlData['Z_SYSTEM_RECONCILE_TIMESTAMP'];
$dateToday = new DateTime(date("Y-m-d H:i"));
$newReconcileDate = date("d-m-Y H:i", strtotime($originalReconcileDate));
$diff = $dateToday->diff($originalReconcileDate);
if($newReconcileDate == "01-01-1970"){
echo '<td></td>';
}else{
echo '<td>'.$newReconcileDate.'</td>';
}
$originalReconcileDate = $sqlData['Z_SYSTEM_RECONCILE_TIMESTAMP'];
$dateToday = new DateTime(date("Y-m-d H:i"));
$newReconcileDate = date("d-m-Y H:i", strtotime($originalReconcileDate));
$diff = $dateToday->diff($originalReconcileDate);
if($newReconcileDate == "01-01-1970"){
echo '<td></td>';
}else{
echo '<td>'.$newReconcileDate.'</td>';
}
echter ik krijg de foutmelding:
Warning: DateTime::diff() expects parameter 1 to be DateTimeInterface, string given in C:\wamp64\www\BP\members\inc\plugin.php on line 2332
echter ik kan 'm niet plaatsen... zal wel iets lulligs zijn maar ik staar me blind.... iemand een idee waar het manco zich bevind?
Er wordt een DateTimeInterface verwacht, en geen string uit je database: $originalReconcileDate.
Dus gebruik $dateToday als argument in die $diff, en gebruik $sqlData['Z_SYSTEM_RECONCILE_TIMESTAMP'] in je new DateTime.
Big chance dat het dan beter gaat.
Gewijzigd op 31/03/2020 21:54:33 door - Ariën -
Niet iedereen zit op Admin niveau :-).... ik probeer het te begrijpen.. (Wat me overigens nog niet lukt hoor.. maar dat terzijde)...
ik doe ook mijn stinkende best..... en gaat wel steeds beter maar ik wil d'r steeds wat bij leren... en ik ik wil het dan ook snappen... maar t'is en blijft lastig om met datums te klooien
edit: en je hebt dus sowieso $newReconcileDate nodig (maar dan in het goede formaat), en niet $originalReconcileDate :).
Gewijzigd op 31/03/2020 22:24:32 door Thomas van den Heuvel
Dirk Huizinga op 31/03/2020 22:16:35:
De error is niet duidelijk!
Niet iedereen zit op Admin niveau :-).... ik probeer het te begrijpen.. (Wat me overigens nog niet lukt hoor.. maar dat terzijde)...
ik doe ook mijn stinkende best..... en gaat wel steeds beter maar ik wil d'r steeds wat bij leren... en ik ik wil het dan ook snappen... maar t'is en blijft lastig om met datums te klooien
Niet iedereen zit op Admin niveau :-).... ik probeer het te begrijpen.. (Wat me overigens nog niet lukt hoor.. maar dat terzijde)...
ik doe ook mijn stinkende best..... en gaat wel steeds beter maar ik wil d'r steeds wat bij leren... en ik ik wil het dan ook snappen... maar t'is en blijft lastig om met datums te klooien
Gelukkig heb je ook https://www.php.net/manual/en/class.datetime.php
En dan de Table of Contents, waarin de functies worden besproken.
php.net. Je kunt daar gewoon DateTime in het zoekvakje inkloppen en je krijgt direct (klasse)definities.
Op deze manier kun je op den duur precies identificeren waar het misgaat, en wat er misgaat. En op een gegeven moment wordt het letten op dit soort fouten tijdens het schrijven van code een tweede natuur, zodat je deze in eerste instantie niet meer maakt, of in ieder geval een groter bewustzijn hebt van de typen van de parameters die functies en methoden verwachten, deze zijn namelijk bijna altijd van een redelijk specifieke voorgeschreven vorm.
In zekere zin is dit weer een vraagstuk waar "het probleem niet het probleem" is, maar het verzamelen van informatie over + het interpreteren van de foutmelding.
@Ariën heeft wel een punt. Leren programmeren wordt zoveel makkelijker wanneer je de foutmeldingen kunt interpreteren. Dit verschaft je enorm veel inzicht. Plus alles is goed gedocumenteerd op Op deze manier kun je op den duur precies identificeren waar het misgaat, en wat er misgaat. En op een gegeven moment wordt het letten op dit soort fouten tijdens het schrijven van code een tweede natuur, zodat je deze in eerste instantie niet meer maakt, of in ieder geval een groter bewustzijn hebt van de typen van de parameters die functies en methoden verwachten, deze zijn namelijk bijna altijd van een redelijk specifieke voorgeschreven vorm.
In zekere zin is dit weer een vraagstuk waar "het probleem niet het probleem" is, maar het verzamelen van informatie over + het interpreteren van de foutmelding.
Je moet verdorie op php.net elke keer een hele statenbijbel doornemen....
jongens bedankt voor het pogen.... maar dit gaat met teveel tijd inzitten.. als ik ooit eens wat meer tijd heb ga ik me er misschien in verdiepen.
Misschien dat je het nu even niet ziet zitten om je concentratie erbij te houden. Ga dan even wat anders doen: Boek lezen, kattenfilmpjes kijken, of lekker naar bed en dan ben je morgen weer fris en fruitig. ;-)
Gewijzigd op 31/03/2020 23:15:41 door - Ariën -
Je moet het zo zien, de methode verwacht een appel, en je stopt er een peer in. Dat past niet. Zorg dat het formaat appel is, en het gaat goed.
En blijkbaar geldt er ook een speciale conditie ($newReconcileDate == "01-01-1970"), in welk geval je in het geheel geen vergelijking hoeft te doen? Mogelijk is het een idee om die datums dan als NULL-waarde op te slaan in je database, dan kun je simpelweg vergelijken met NULL.
Wat is trouwens het formaat van $sqlData['Z_SYSTEM_RECONCILE_TIMESTAMP']? Is dit gewoon een UNIX-timestamp? Dan kan de code waarschijnlijk ook nog wat korter. Helemaal handig zou het zijn als deze informatie ook gewoon als (NULLable) DATETIME-kolom wordt opgeslagen, dan hoef je ook niet tig vertaalslagen uit te voeren.
ik heb in mijn SQL SELECT de datum format van de tabel Z_SYSTEM_RECONCILE_TIMESTAMP aangegeven. De uren, minuten en secondes zijn in deze nl niet zo van belang.
Dit heb ik als volgt gedaan:
Code (php)
1
2
3
2
3
$sql = "SELECT DATE_FORMAT(idm_doelsysteem.Z_SYSTEM_RECONCILE_TIMESTAMP, '%d-%m-%Y') AS originalReconcileDate,
enz, enz enz
enz, enz enz
Voor uiteindelijk het verschil tussen twee datums weer te geven heb ik dit als volgt gedaan:
Code (php)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
//* RECONCILATION INSTELLINGEN
$reconDay = new DateTime($sqlData['originalReconcileDate']);
$dateToday = new DateTime();
$diff = $dateToday->diff($reconDay);
if($sqlData['originalReconcileDate'] == NULL){
echo '<td><font color="red">Nog geen recon ingericht!</font></td>';
}else{
echo '<td>'.$reconDay->format('d-m-Y').' <font size="1">('.$diff->format('%d dagen geleden').')</font></td>';
$reconDay = new DateTime($sqlData['originalReconcileDate']);
$dateToday = new DateTime();
$diff = $dateToday->diff($reconDay);
if($sqlData['originalReconcileDate'] == NULL){
echo '<td><font color="red">Nog geen recon ingericht!</font></td>';
}else{
echo '<td>'.$reconDay->format('d-m-Y').' <font size="1">('.$diff->format('%d dagen geleden').')</font></td>';
Opmerking: Goeie tip om wat anders te doen. Als je er een lange dag op hebt zitten en en je blind staart moet je dit soort dingen dus gewoon niet doen....
Bedankt voor alle goed bedoelde adviezen.
Gewijzigd op 01/04/2020 10:57:32 door - DHU -
Met vallen en opstaan lukt veel. Ok het gaat wat traag:)
Je kan toch niet willen dat de mensen hier jouw code schrijven.
Enkel als voorbeeld: Net een scriptje van vroeger eens hermaakt. Dubbel zo snel en 3k kleiner. Gewoon betere query's.
Ivo P op 01/04/2020 19:55:00:
Hmmm interesting.. thnx... Ga ik zeker mee experimenteren. Heb nl wel op meerdere plekker het vershil dagen benodigd.. Lekker kort en krachtig. Komt de code alleen maar ten goede
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
<?php
//* RECONCILATION INSTELLINGEN
$reconDay = new DateTime($sqlData['originalReconcileDate']);
$dateToday = new DateTime();
$diff = $dateToday->diff($reconDay);
if($sqlData['originalReconcileDate'] == NULL){
echo '<td><font color="red">Nog geen recon ingericht!</font></td>';
}else{
echo '<td>'.$reconDay->format('d-m-Y').' <font size="1">('.$diff->format('%d dagen geleden').')</font></td>';
}
?>
//* RECONCILATION INSTELLINGEN
$reconDay = new DateTime($sqlData['originalReconcileDate']);
$dateToday = new DateTime();
$diff = $dateToday->diff($reconDay);
if($sqlData['originalReconcileDate'] == NULL){
echo '<td><font color="red">Nog geen recon ingericht!</font></td>';
}else{
echo '<td>'.$reconDay->format('d-m-Y').' <font size="1">('.$diff->format('%d dagen geleden').')</font></td>';
}
?>
Je maakt hier wel een fout, en een aantal dingen kunnen handiger gestructureerd worden. Je kunt er natuurlijk ook voor kiezen om alles in de query te regelen maar mogelijk is het handiger/makkelijker om code aan te passen dan SQL, dit moet je zelf weten.
Allereerst (en dit is dus een echte fout): DateInterval heeft formatteringsregels die mogelijk anders werken dan je zou denken. Het %d formatteringskarakter geeft je het aantal dagen verschil na aftrek van eventuele maanden.
Stel je hebt dus bijvoorbeeld 1 april en 2 mei, dan levert %d jou 1 (1 maand en 1 dag) in plaats van 31 dagen, wat je misschien zou verwachten. Hiervoor is %a bedoeld, zie ook de documentatie. Misschien wil je dat nog even aanpassen als je deze aanpak nog gebruikt voordat er mensen in de paniek schieten :p.
Dan ga je dingen uitrekenen die mogelijk helemaal niet uitgerekend hoeven te worden. Nu maakt dat in dit geval niet zo uit voor de snelheid, maar wat als deze berekening vele male complexer/duurder was? Staat je webserver mogelijk heel vaak te stampen op dingen die niet eens nodig zijn... dit is pure verspilling. Begin dus met het if-statement.
Ook kun je de programmeer- en weergavelogica verder uit elkaar trekken zodat je uiteindelijk een duidelijke streep tussen deze twee kunt aanbrengen.
Bijvoorbeeld dus als volgt:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
if ($sqlData['originalReconcileDate'] == NULL) {
$class = 'warning'; // geef het ding een opmaak
$output = 'Nog geen recon ingericht!';
} else {
// hier ga je pas rekenen
$reconDay = new DateTime($sqlData['originalReconcileDate']);
$dateToday = new DateTime();
$diff = $dateToday->diff($reconDay);
$class = 'message';
$output = $reconDay->format('d-m-Y').' <span>('.$diff->format('%a').' dag(en) geleden)</span>';
}
?><td class="<?php echo $class; ?>"><?php echo $output; ?></td>
if ($sqlData['originalReconcileDate'] == NULL) {
$class = 'warning'; // geef het ding een opmaak
$output = 'Nog geen recon ingericht!';
} else {
// hier ga je pas rekenen
$reconDay = new DateTime($sqlData['originalReconcileDate']);
$dateToday = new DateTime();
$diff = $dateToday->diff($reconDay);
$class = 'message';
$output = $reconDay->format('d-m-Y').' <span>('.$diff->format('%a').' dag(en) geleden)</span>';
}
?><td class="<?php echo $class; ?>"><?php echo $output; ?></td>
Hier verplaats je ook hoe td.warning, td.message en td.message span er verder uitzien naar een stylesheet, dit wil je loskoppelen van de HTML, mocht je dit ooit nog willen aanpassen dan kun je dat puur in CSS regelen en hoef je geen code op te breken...
Gewijzigd op 02/04/2020 02:27:35 door Thomas van den Heuvel
Ik heb dit nooit kunnen bedenken om een berekening met if statement te beginnen. Maar ondank ik in dit geval niet zoveel merk van de berekeninstijd hoor... deze gaat rap genoeg..maar inderdaad met 'n wat complexere berekening zou dit zo maar anders kunnen. Goed punt.
Dan over de opmaak... ik ben ook maar 'n ouwe zak hoor.. ik kom nog uit de html 1.0 periode. CSS wat was dat :-)
Ben daar helemaal niet in meegegroeid dus ik betrap me er vaak op dat ik de opmaak elke keer tussen de codering plaats. Ook hier onderga ik nog een leerproces:
Maar ik wil je nogmaals bedanken voor deze toelichting. Top!!!