Een datum verlengen met vooraf gesteld aantal dagen
Ik ben bezig met een soort premium system voor de leden van mijn website.
Ze kunnen bijvoorbeeld 365 dagen kopen. Dan zet sla ik de datum van volgendjaar op in de database (2011-11-13 12:40:00 > bijvoorbeeld).
Maar stel stel dat een gebruiker voor de 13e volgendjaar weer opnieuw premium koopt, dan moet er bij de afloop datum van zijn premium 365 dagen getelt worden.
En ik heb al zoveel verschillende dingen geprobeerd, maar ik krijg het maar niet goed. Hopelijk weet iemand van jullie het.
Groetjes, Erik
Quote:
En ik heb al zoveel verschillende dingen geprobeerd, maar ik krijg het maar niet goed. Hopelijk weet iemand van jullie het.
en mogen we dan ook nog meegenieten van wat je dan zoal geprobeerd hebt. het is vaak eenvoudiger om ergens op in te haken om je fout uit te leggen - ook voor anderen zal het dan duidelijker zijn - dan dat je een open vraag stelt.
Gewijzigd op 13/11/2010 13:07:00 door Noppes Homeland
$nu = strtotime('now');
$verschil = $ooit - $nu;
$aantal_dagen = ceil($verschil/86400);
Dat geeft het aantal dagen dat hij nu nog premium heeft, en die dus bij de nieuw gekochte dagen moeten komen.
als je nu deze:
date('Y-m-d', strtotime('+1 day))
en dan die 1 kan vervangen door een $variable, dan zou het probleem opgelost zijn, alleen dat lukt me niet zover ik zie.
update tabel set pdatum = pdatum + interval 365 day where klant_id = 1
update tabel set pdatum = pdatum + interval 1 year where klant_id = 1
En waarom lukt dat dan niet? Het is gewoon een kwestie van weten hoe je variabelen buitn quotes plaats en het geheel toch een string is
Gewijzigd op 13/11/2010 13:41:23 door Noppes Homeland
Date_add uitleg: http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_date-add
http://www.w3schools.com/SQl/func_date_add.asp
Of nog mooier: als je zorgt dat premiumDate standaard NULL is dan kan je automatisch als iemand voor het eerst premium bestelt een jaar na nu instellen, zo niet dan een jaar bij al ingevulde datum optellen:
Code (php)
1
UPDATE tabelnaam SET premiumDate = DATE_ADD(IFNULL(premiumDate, NOW()), INTERVAL 1 YEAR)
Uitleg: http://dev.mysql.com/doc/refman/5.0/en/control-flow-functions.html#function_ifnull
De kolom moet datetime of date zijn. Conclusie: gebruik de kracht van MySQL als dat kan XD.
Dus als we jouw queries loslaten op ORACLE/PG/SQL Server dan krijgen we heel fijn een melding om de oren en moeten we eerst de MySql DATE_ADD functie gaan inplementeren.
en elke fatabase heeft ook zo z'n eigen IFNULL
zie: http://www.w3schools.com/sql/sql_isnull.asp
en uiteraard kauwen we niet alles in 1 keer voor.
Gewijzigd op 13/11/2010 15:04:53 door Noppes Homeland
http://mssql-to-postgresql.blogspot.com/2006/04/dateadd.html. Het idee dat je jezelf zou moeten beperken omdat iets niet tot de standaard behoord terwijl ELKE fatsoenlijke RDBMS een implementatie ervan heeft is belachelijk. En nee, je hoeft dus ook niet zelf de MySQL DATE_ADD functie te gaan implementeren!
Wat betreft het voorkauwen: mee eens.
Zowieso heeft elke SQL taal andere syntax, dus je moet dan toch al je queries gaan herschrijven als je zelf je queries schrijft. Gebruik je een goed framework dan hoeft dat niet. 99% kans dat Erik MySQL gebruikt, dus ik heb die aanname maar gedaan zodat ik niet hoefde te wachten op zijn antwoord. Met het gebruik van datetime functies is niets mis! Elke taal heeft zijn eigen syntax, lees dit maar eens door: Wat betreft het voorkauwen: mee eens.
EN dan nog zal het meerendeel niet in je php code staan maar zal je de views moeten aanpassen, wat dan een stuk makkelijker is dan al je queries in je code te moeten nalopen.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
// Verloopdatum berekenen
$secinjaar = 60 * 60 * 24 * 365;
$verlooptime = time() + $secinjaar;
// Klant koopt meer premium (bijv. half jaar)
$secinhalfjaar = 60 * 60 * 24 * (365 / 2);
$verlooptime = $verlooptime + $secinhalfjaar;
// Controle of premium is afgelopen
if(time() > $verlooptime) {
echo 'premium verlopen';
} else {
echo 'Je hebt nog premium!';
}
?>
// Verloopdatum berekenen
$secinjaar = 60 * 60 * 24 * 365;
$verlooptime = time() + $secinjaar;
// Klant koopt meer premium (bijv. half jaar)
$secinhalfjaar = 60 * 60 * 24 * (365 / 2);
$verlooptime = $verlooptime + $secinhalfjaar;
// Controle of premium is afgelopen
if(time() > $verlooptime) {
echo 'premium verlopen';
} else {
echo 'Je hebt nog premium!';
}
?>
Dit werkt dus met timestamps: ALTIJD betrouwbaar :D
Moet je alleen nog wel even uitvissen hoeveel seconden jij in een jaar wil, want je kunt het berekenen op de volgende manieren:
60 * 60 * 24 * 365
60 * 60 * 24 * 365.25 (schrikkeljaar)
60 * 60 * 7 * 52 (met weken)
@Gerben, gij moge dan wel zo lekker aan kloten, maar op den duur loop je met zulk soort code toch tegen de lamp.
Noppes Homeland op 13/11/2010 16:01:36:
Ik heb ook nergens geschreven dat je specifieke SQL functies moet meiden, maar wel dat je zoveel mogelijk Standaard SQL moet gebruiken, dan weet je welke queries je moet aanpassen als je overgaat naar een andere database.
EN dan nog zal het meerendeel niet in je php code staan maar zal je de views moeten aanpassen, wat dan een stuk makkelijker is dan al je queries in je code te moeten nalopen.
EN dan nog zal het meerendeel niet in je php code staan maar zal je de views moeten aanpassen, wat dan een stuk makkelijker is dan al je queries in je code te moeten nalopen.
Noppes, ik vind het hartstikke goed dat je nadenkt over zaken als standaarden en portabiliteit. Perfectionisme kenmerkt goede programmeurs. Ik wil enkele kanttekeningen maken zodat je hopelijk inziet dat je op een aantal punten de plank misslaat. In je vorige bericht zeg je overigens nog "DATE_ADD is wrong, dat is geen Standaard SQL!!". Dus beweren dat je nergens geschreven hebt dat je specifieke SQL functies moet mijden (niet meiden XD) lijkt me een beetje dubieus. En wat hebben views hiermee te maken? Je zult altijd je queries na moeten lopen omdat elke taal andere syntax heeft. Standard SQL != een vaste syntax. Daarnaast: als je zo'n grote website hebt dat het nalopen van queries (die je als het goed is netjes hebt gegroupeerd in models) een probleem gaat worden in het kleine geval dat je van database moet wisselen dan had je daar van tevoren over na moeten denken en een framework moeten gebruiken die als extra abstractielaag boven SQL zit. Dan hoef je i.p.c. alleen in de config te zeggen dat je bijv. naar postgreSQL gaat en werkt alles! Uit eigen ervaring moet ik zeggen dat het opeens gebruik moeten maken van een andere database in de praktijk nauwelijks voor komt.
Het punt om WEL gebruik te maken van dergelijke functies is het verhogen van de abstractie van je code. Je legt in één regel uit wat je wilt doen, de compiler begrijpt wat je wilt doen en voert dat op de meest efficiënte manier uit. Een compiler snapt die hele PHP meuk niet en zal dus nauwelijks geoptimaliseerd kunnen worden. Ik verzin dit niet zelf. Bij de presentatie van één van de hoofdprogrammeurs van Microsoft op de Dev Days 2010 (Anders Hejlsberg - Trends and Future Directions in Programming Languages) wordt aangegeven dat dit één van de belangrijkste ontwikkelingen gaat worden in het programmeren. Het programmeren zal steeds abstracter worden (je zegt in mijn voorbeeld: ik wil er een jaar bij, niets meer niets minder). Je loopt dan niet tegen problemen aan zoals met het PHP voorbeeld. Gerben, je geeft al drie voorbeelden van wat een definitie kan zijn van een jaar. Typerend is dat geen de correcte is. Wat de definitie van een jaar is moet je niet eens over na willen denken. Dit leidt tot aannames en fouten. In goede code beschrijf je WAT er moet gebeuren en niet HOE dat moet gebeuren. Zoek de presentatie en bijbehorende sheets eens op: deze zou eigenlijk door elke programmeur gezien moeten worden.
Extra opmerking: met bovenstaand code voorbeeldje ben je er nog niet. Je zult nog steeds handmatig gaan controleren of er al een datum is ingevuld, extra ifjes maken, en de data moet je nog opslaan. Tot slot Gerben: waarom zouden timestamps betrouwbaarder zijn dan datetime? Timestamps zijn niet op een normale manier leesbaar en mede daarom verouderd.