Search code examples
phpdatediffwoocommerce-bookings

Calculate how many days (Monday - Wednesday) between two dates - Woocommerce Bookings?


I am struggling with the price calculation of Woocommerce Bookings for the type "days". If the price on a daterange (e.g. Monday to Wednesday or Wednesday-Saturday or Sunday-Tuesday...) is higher than on the other days.

So far I know how many days:

$days = date_diff($from, $to)->format('%d');

This question helps to get the number of single days: calculate sundays between two dates

But how do I get not only "sundays" but every daterange (e.g. from 6 to 2) with this:

$sundays = intval($days / 7) + ($from->format('N') + $days % 7 >= 7);

I guess I need to iterate through daterange and use this formula but I cannot figure out how.


Solution

  • You can use a completely different approach: Create a DatePeriod object and loop through the Period object and increment a variable each time you encounter the range.

    The following code achieve it but only return the number of complete range:

    $from='2018/09/1';
    $to='2018/09/31';
    
    $start='Sunday';
    $end='Thursday';
    
    $go=false;
    $period=new DatePeriod(date_create($from),date_interval_create_from_date_string('1 days'),date_create($to));
    $nRange=0;
    foreach($period as $date){
        if($date->format('l')===$start){
            $go=true;
    
        }
        if($go&&$date->format('l')===$end){
            $go=false;
            $nRange++;
        }
    }
    
    print_r($nRange);
    

    output :

    4
    

    It works fine for any chosen range.

    However if the need is to get any valid day within the given range complete or not you can alter the previous code this way:

     $from='2018/09/17';
        $to='2018/09/31';
        $start='Sunday';
        $end='Thursday';
        $day_num=['Monday'=>1,'Tuesday'=>2,'Wednesday'=>3,'Thursday'=>4,'Friday'=>5,'Saturday'=>6,'Sunday'=>7];
        $start_num=$day_num[$start];
        $end_num=$day_num[$end];
    
    
        $period=new DatePeriod(date_create($from),date_interval_create_from_date_string('1 days'),date_create($to));
        $nRange=0;
    
        if($start_num===$end_num){
            $valid_range=array_values($day_num);//keep the number of each day of the week
        }
        elseif($start_num>$end_num){
            $valid_range=array_values($day_num);//keep the number of each day of the week
            while($valid_range[0]!==$start_num){//rotate the values to keep the start day first
                $pop=array_shift($valid_range);
                array_push($valid_range,$pop);
    
            }
            $valid_range=array_slice($valid_range,array_search($start_num,$valid_range),$start_num-$end_num);//keep only the days in the chosen range
        }else{
            $valid_range=array_values($day_num);//keep the number of each day of the week
            $valid_range=array_slice($valid_range,array_search($start_num,$valid_range),$end_num-$start_num); //keep only the days in the chosen range
        }
        $valid_range=array_flip($valid_range);//flip the array to make the search more fast
        foreach($period as $date){
            if(isset($valid_range[(int)$date->format('N')])){
                $nRange++;
            }
        }
    
        print_r($nRange);//output the number  of valid days 
    

    ouput:

     6