Hoi,

Ik zou graag beginnen met een korte schets

Ik ben bezig met een project (verhuring van vakantie woning van en vriend). Er wordt gewerkt met maximaal 5 seizoenen

1. Laag is van 01.11 tot 31.03 prijs 325,-
2. Mid1 is van 01.04 tot 30.06 prijs 375,-
3. Hoog is van 01.07 tot 31.08 prijs 575,-
4. Mid2 is van 01.09 tot 31.10 prijs 375,-
deze liggen vast, de 5de kan al dan niet geactiveerd worden bvb rond de kerstperiode uiteindelijk is het principe van berekenen hetzelfde (vermoed ik).
het jaartal speelt geen rol.

misschien nu al en stukje code die ik heb


<?php
$converted_startdate = date('Y-m-d',strtotime($startingdate));
$converted_enddate = date('Y-m-d',strtotime($endingdate));

hieronder het stukje waarbij de data haal uit de database

$propertyresult = mysql_query("SELECT * FROM propertiesmain WHERE propertiesmain_id = '$propID'");
if (mysql_num_rows($propertyresult) > 0) {
	$psubrow = mysql_fetch_assoc($propertyresult);
	$propertyCode = $psubrow['propertiesmain_code'];
	
	// current year + 1
	$current_year = date("Y");
	$year_plus_1 = date("Y", strtotime("+1 years", strtotime(date("Y"))));
	$year_min_1 = date("Y", strtotime("-1 years", strtotime(date("Y"))));
	
	// table 1 periode and price
	$tablestart1_org = date('Y-m-d',strtotime($psubrow['propertiesmain_tablestart1']));
	$tablestart1_replaced = substr_replace($tablestart1_org,"2017",0,4); // no matter what year convert to 2017
	$tablestart1_replaced1 = substr_replace($tablestart1_org,$year_min_1,0,4); // no matter what year convert one year back
	$tableend1_org = date('Y-m-d',strtotime($psubrow['propertiesmain_tableend1']));
	$tableend1_replaced = substr_replace($tableend1_org,$year_plus_1,0,4);
	$tableend1_replaced1 = substr_replace($tableend1_org,$current_year,0,4);
	$tableprice1 = $psubrow['propertiesmain_tableprice1'];
	
	// table 2 periode and price
	$tablestart2_org = date('Y-m-d',strtotime($psubrow['propertiesmain_tablestart2']));
	$tablestart2_replaced = substr_replace($tablestart2_org,"2017",0,4); // no matter what year convert to 2017
	$tablestart2_replaced1 = substr_replace($tablestart2_org,$year_min_1,0,4); // no matter what year convert to 2017
	$tableend2_org = date('Y-m-d',strtotime($psubrow['propertiesmain_tableend2']));
	$tableend2_replaced = substr_replace($tableend2_org,$current_year,0,4); 
	$tableprice2 = $psubrow['propertiesmain_tableprice2'];
	
	// table 3 periode and price
	$tablestart3_org = date('Y-m-d',strtotime($psubrow['propertiesmain_tablestart3']));
	$tablestart3_replaced = substr_replace($tablestart3_org,"2017",0,4); // no matter what year convert to 2017
	$tablestart3_replaced1 = substr_replace($tablestart3_org,$year_min_1,0,4); // no matter what year convert to 2017
	$tableend3_org = date('Y-m-d',strtotime($psubrow['propertiesmain_tableend3']));
	$tableend3_replaced = substr_replace($tableend3_org,$current_year,0,4);
	$tableprice3 = $psubrow['propertiesmain_tableprice3'];
	
	// table 4 periode and price
	$tablestart4_org = date('Y-m-d',strtotime($psubrow['propertiesmain_tablestart4']));
	$tablestart4_replaced = substr_replace($tablestart4_org,"2017",0,4); // no matter what year convert to 2017
	$tablestart4_replaced = substr_replace($tablestart4_org,"2017",0,4); // no matter what year convert to 2017
	$tableend4_org = date('Y-m-d',strtotime($psubrow['propertiesmain_tableend4']));
	$tableend4_replaced = substr_replace($tableend4_org,$current_year,0,4);
	$tableprice4 = $psubrow['propertiesmain_tableprice4'];
	
	// table 5 periode and price
	$tablestart5_org = date('Y-m-d',strtotime($psubrow['propertiesmain_tablestart5']));
	$tablestart5_replaced = substr_replace($tablestart5_org,"2017",0,4); // no matter what year convert to 2017
	$tableend5_org = date('Y-m-d',strtotime($psubrow['propertiesmain_tableend5']));
	$tableend5_replaced = substr_replace($tableend5_org,$current_year,0,4);
	$tableprice5 = $psubrow['propertiesmain_tableprice5'];
	
	// winter specials
	$longterm_periode = $psubrow['propertiesmain_duration'];
	$longterm_price = $psubrow['propertiesmain_longtermprice'];
	
	// cost of final cleaning
	$FinalCleaningCost = $psubrow['propertiesmain_endcleaning'];
	// deposite
	$DepositeGuarentee = $psubrow['propertiesmain_guarentee'];
											
}else{
	show_alert('ERROR: Could not find property!');
	die();
}
?>


wat voorlopig werkt is, indien een boeking plaats vindt binnen éénzelfde seizoensperiode dit doe ik zo


<?php
// table 1 ??
if (($converted_startdate >= $tablestart1_replaced) AND ($converted_enddate <= $tableend1_replaced)) {
	$daycost = number_format(($tableprice1 / 7),2); // convert from week price to daily price
	
	$holidaycost = number_format($totaldays * $daycost,2); // number of days times day price
	$seasson = 'Low';
	
	// winterprice is possible check if within winter period
	if ($weeks >= $longterm_periode){
		$daycost = number_format(($longterm_price / 7),2); // convert from week price to daily price
		
		$holidaycost = number_format($totaldays * $daycost,2); // number of days times day price
		$winterprice = 1; //mark that winterprice is being used
		$seasson = 'Winter';
	}
}		

// table 2 ??
if ($converted_startdate >= $tablestart2_replaced AND $converted_enddate <= $tableend2_replaced) {
	$daycost = number_format(($tableprice2 / 7),2); // convert from week price to daily price
	
	$holidaycost = number_format($totaldays * $daycost,2); // number of days times day price
	$seasson = 'Mid';
}
// table 3 ??
if ($converted_startdate >= $tablestart3_replaced AND $converted_enddate <= $tableend3_replaced) {
	$daycost = number_format(($tableprice3 / 7),2); // convert from week price to daily price
	
	$holidaycost = number_format($totaldays * $daycost,2); // number of days times day price
	$seasson = 'High';
}
// table 4 ??
if ($converted_startdate >= $tablestart4_replaced AND $converted_enddate <= $tableend4_replaced) {
	$daycost = number_format(($tableprice4 / 7),2); // convert from week price to daily price
	
	$holidaycost = number_format($totaldays * $daycost,2); // number of days times day price
	$seasson = 'Mid';
}
// table 5 ??
if ($converted_startdate >= $tablestart5_replaced AND $converted_enddate <= $tableend5_replaced) {
	$daycost = number_format(($tableprice5 / 7),2); // convert from week price to daily price
	
	$holidaycost = number_format($totaldays * $daycost,2); // number of days times day price
	$seasson = 'Extra';
}
?>


bovenstaand lijkt tot heden goed te werken, maar nu komt het. er kunnen uiteindelijk ook seizoen overschrijdende boekingen plaats vinden, dus waarvan xx dagen is één seizoen en xx aantal dagen in daaropvolgend seizoen. In theorie kwam ik met de oplossing als volgt

stap 1. bereken het totaal aantal vakantie nachten
stap 2. kijk na in welke table (seizoen) de aankomst datum start
stap 3. bereken het aantal dagen tot einde van deze table (einde start seizoen dus)
stap 4. trek restdagen af van het totaal aantal vakantie nachten, en je bekomt het rest aantal nachten in volgend seizoen

dit lijkt me een juiste beredenering toch?
maar in de praktijk dit omzetten in php loopt dus mis, en daarom hier m'n vraag wat doe ik verkeerd???
onderstaand is wat ik heb


<?php
// calculate days 
$holidayduration = floor(strtotime($converted_enddate) - strtotime($converted_startdate));
$holidayduration = floor($holidayduration/(60*60*24));

// if starts in low seasson and runs over end of low seasson
if (($converted_startdate >= $tablestart1_replaced1) && ($converted_enddate > $tableend1_replaced1)) {
	$daycost1 = 0;
	$daycost2 = 0;
	$daycost = 0;
	
	// calculate days in and days over
	$overspilled = floor(strtotime($converted_enddate) - strtotime($tableend1_replaced1));
	//$holidays = floor($holidays/(60*60*24)) + 1;
	$overspilled = floor($overspilled /(60*60*24));
		
	$normaldays = $holidayduration - $overspilled;
	$daycost1 = number_format(($tableprice1 / 7),2); // convert from week price to daily price
	$holidaycostl = number_format($normaldays * $daycost1,2);
	//echo 'days1 '.$normaldays.' cost1 '.$holidaycostl.'<br>';
		
	$daycost2 = number_format(($tableprice2 / 7),2); // convert from week price to daily price
	$holidaycost2 = number_format($overspilled * $daycost2,2);
	//echo 'days2 '.$overspilled.' cost1 '.$holidaycost2.'<br>';
	
	$holidaycost = number_format($holidaycostl + $holidaycost2,2); // number of days times day price
	//echo '<br>low to mid holidaycost '.$holidaycost;
	$seasson = 'Low-Mid';
}

// if starts in mid seasson and runs over end of mid seasson
if (($converted_startdate >= $tablestart2_replaced1) && ($converted_enddate > $tableend2_replaced)) {
	$daycost1 = 0;
	$daycost2 = 0;
	$daycost = 0;

	// calculate days in and days over
	$overspilled = floor(strtotime($converted_enddate) - strtotime($tableend2_replaced));
	//$holidays = floor($holidays/(60*60*24)) + 1;
	$overspilled = floor($overspilled /(60*60*24));
	
	$normaldays = $holidayduration - $overspilled;
	$daycost1 = number_format(($tableprice2 / 7),2); // convert from week price to daily price
	$holidaycostl = number_format($normaldays * $daycost1,2);
				
	$daycost2 = number_format(($tableprice3 / 7),2); // convert from week price to daily price
	$holidaycost2 = number_format($overspilled * $daycost2,2);
		
	$holidaycost = number_format($holidaycostl + $holidaycost2,2); // number of days times day price
	//echo '<br>mid to high holidaycost '.$holidaycost;
	$seasson = 'Mid-High';
}

// if starts in high seasson and runs over end of high seasson
if (($converted_startdate >= $tablestart3_replaced1) && ($converted_enddate > $tableend3_replaced)) {
	$daycost1 = 0;
	$daycost2 = 0;
	$daycost = 0;

	// calculate days in and days over
	$overspilled = floor(strtotime($converted_enddate) - strtotime($tableend3_replaced));
	//$holidays = floor($holidays/(60*60*24)) + 1;
	$overspilled = floor($overspilled /(60*60*24));

	$normaldays = $holidayduration - $overspilled;

	$daycost1 = number_format(($tableprice3 / 7),2); // convert from week price to daily price
	$holidaycostl = number_format($normaldays * $daycost1,2);
		
	$daycost2 = number_format(($tableprice4 / 7),2); // convert from week price to daily price	
	$holidaycost2 = number_format($overspilled * $daycost2,2);
	$holidaycost = number_format($holidaycostl + $holidaycost2,2); // number of days times day price
	//echo '<br>high to mid2 holidaycost '.$holidaycost;
	$seasson = 'High-Mid';
}

// if starts in mid2 seasson and runs over end of mid2 seasson
if (($converted_startdate >= $tablestart4_replaced1) && ($converted_enddate > $tableend4_replaced)) {
	$daycost1 = 0;
	$daycost2 = 0;
	$daycost = 0;

	// calculate days in and days over
	$overspilled = floor(strtotime($converted_enddate) - strtotime($tableend4_replaced));
	//$holidays = floor($holidays/(60*60*24)) + 1;
	$overspilled = floor($overspilled /(60*60*24));

	$normaldays = $holidayduration - $overspilled;

	$daycost1 = number_format(($tableprice4 / 7),2); // convert from week price to daily price
	$holidaycostl = number_format($normaldays * $daycost1,2);
	
	$daycost2 = number_format(($tableprice5 / 7),2); // convert from week price to daily price	
	$holidaycost2 = number_format($overspilled * $daycost2,2);

	$holidaycost = number_format($holidaycostl + $holidaycost2,2); // number of days times day price
	//echo '<br>mid2 to exta holidaycost '.$holidaycost;
	$seasson = 'Mid-Ext';
}

// if starts in extra seasson and runs over end of extra seasson
if (($converted_startdate >= $tablestart5_replaced1) && ($converted_enddate > $tableend5_replaced)) {
	$daycost1 = 0;
	$daycost2 = 0;
	$daycost = 0;

	// calculate days in and days over
	$overspilled = floor(strtotime($converted_enddate) - strtotime($tableend5_replaced));
	//$holidays = floor($holidays/(60*60*24)) + 1;
	$overspilled = floor($overspilled /(60*60*24));

	$normaldays = $holidayduration - $overspilled;

	$daycost1 = number_format(($tableprice5 / 7),2); // convert from week price to daily price
	$holidaycostl = number_format($normaldays * $daycost1,2);
	
	$daycost2 = number_format(($tableprice1 / 7),2); // convert from week price to daily price	
	$holidaycost2 = number_format($overspilled * $daycost2,2);

	$holidaycost = number_format($holidaycostl + $holidaycost2,2); // number of days times day price
	//echo '<br>ext to low holidaycost '.$holidaycost;
	$seasson = 'Ext-Low';
}
?>


ergens maak ik dus fouten, ik dacht na dagen van proberen dat ik het gevonden van (test van laag naar mid1 seizoen) dit dus gecopieerd en aangepast voor de volgende seizoenen, maar gisteren bleek bij test boeking van 30.09 tot 30.11 het is te lopen en ook een test boeking van 29.06.(2018) tot 14.07.(2018) volledig mis te lopen. dus telkens bij overschrijding van en seizoen.

Dus mijn vraag is, of iemand mij kan tonen waar ik in de fout ga, of mij op weg kan helpen? ik neem aan dat veel anders en beter geschreven kan worden, maar da's zoals ik php ken, ben 56 en tot heden alles zlf geleerd door naar veel voorbeelden te kijken. Enfin, ik hoop dat iemand mij wil/kan helpen

alvast bedankt voor alle feedback
marc

Je rekent nu met 60*60*24 voor dagen en voert allerlei stringoperaties uit. Dat is nergens voor nodig: maak het jezelf makkelijk met de speciale objecten voor datums en tijden DateTime, DateInterval en DatePeriod.

Ik heb een voorbeeld voor je uitgewerkt, zodat je ziet hoe je die drie samen kunt gebruiken:


<?php
// Tijdzone voor o.a, Nederland en België
date_default_timezone_set('Europe/Amsterdam');

// Huidig jaar
define('CURRENT_YEAR', date('Y'));

/**
 * Seizoenen en prijzen
 *
 * 1. Laag is van 01.11 tot 31.03 prijs 325,-
 * 2. Mid1 is van 01.04 tot 30.06 prijs 375,-
 * 3. Hoog is van 01.07 tot 31.08 prijs 575,-
 * 4. Mid2 is van 01.09 tot 31.10 prijs 375,-
 */
$seasons = array(
    1 => new \DatePeriod(
        new \DateTime(CURRENT_YEAR . '-11-01'),
        new \DateInterval('P1D'),
        new \DateTime(CURRENT_YEAR + 1 . '-04-01')
    ),
    2 => new \DatePeriod(
        new \DateTime(CURRENT_YEAR . '-04-01'),
        new \DateInterval('P1D'),
        new \DateTime(CURRENT_YEAR . '-07-01')
    ),
    3 => new \DatePeriod(
        new \DateTime(CURRENT_YEAR . '-07-01'),
        new \DateInterval('P1D'),
        new \DateTime(CURRENT_YEAR . '-09-01')
    ),
    4 => new \DatePeriod(
        new \DateTime(CURRENT_YEAR . '-09-01'),
        new \DateInterval('P1D'),
        new \DateTime(CURRENT_YEAR . '-11-01')
    ),
);

$prices = array(
    1 => 325,
    2 => 375,
    3 => 575,
    4 => 375,
);

/**
 * Test case: boeking voor 8 dagen vanaf 25 juni, dus met een overlapping
 * tussen seizoen 2 en seizoen 3.  De eerste twee variabelen $start en $days 
 * haal je later uit een formulier voor nieuwe boekingen of een database
 * voor bestaande boekingen.
 */
$start = new \DateTime(CURRENT_YEAR . '-06-25');
$days = 8;
$rental_period = new \DatePeriod($start, new \DateInterval('P1D'), $days - 1);
$rental_price = 0;

echo '<pre>';
foreach ($rental_period as $date) {
    foreach ($seasons as $key => $season) {
        foreach ($season as $day) {
            if ($date == $day) {
                echo $date->format('Y-m-d') . ' kost ' . $prices[$key];
                echo PHP_EOL;
                $rental_price += $prices[$key];
            }
        }
    }
}

echo 'Totale kosten: ' . $rental_price;
?>


Output:


2017-06-25 kost 375
2017-06-26 kost 375
2017-06-27 kost 375
2017-06-28 kost 375
2017-06-29 kost 375
2017-06-30 kost 375
2017-07-01 kost 575
2017-07-02 kost 575
Totale kosten: 3400
Een andere manier, ook meer variabel qua prijs en qua blokkade: Zet het hele jaar per dag in een MySQL tabel en in deze tabel plaats je dan de datum, de prijs (per nacht) en een vlaggetje voor geblokkeerd en/of schrikkeldag.
Het enige dat je dan moet doen bij een reservering is een SQL, grofweg:

SELECT sum(prijs), count(1)
FROM jaar_dag_tabel
WHERE datum between $begin_datum AND $eind_datum
AND geblokkeerd = 0

Je kan hiermee per dag de prijs flexibel bijstellen zonder php code aan te passen.
Dagen blokkeren (gereserveerd of geen schrikkeldag)

Vooraf maak je een telling van het aantal nachten (verschil tussen $eind_datum - $begin_datum) en dat moet dan overeenkomen met het resultaat van de count. Zoniet dan is er iets aan de hand, het overlapt bijvoorbeeld reeds gereserveerde of geblokkeerde dagen.
alvast bedankt voor de feedback - ik kan weer verder schrijven

Reageren