Although the answer has already been provided, here is a small snippet with a class that handles everything for you:
<?php class dateRange { protected $start, $end, $daysToExclude, $datesToExclude; function __construct($dateStart, $dateEnd, $daysToExclude, $datesToExclude) { $this->start = $dateStart; $this->end = $dateEnd; $this->daysToExclude = $daysToExclude; $this->datesToExclude = $this->fixFormat($datesToExclude); } public function getRangeLength ($callback = null) { $tmp = array(); $now = strtotime($this->start); $to = strtotime($this->end); while ( $now <= $to ) { if (!in_array(date("w", $now), $this->daysToExclude)) { $tmp[] = date('dm-Y', $now); } $now = strtotime('+1 day', $now); } is_callable($callback) && call_user_func($callback, array_diff($tmp,$this->datesToExclude)); return count(array_diff($tmp,$this->datesToExclude)); } private function fixFormat($el) { if (!is_array($el)) { return false; } else { foreach ($el as &$value) { $value = date("dmY",strtotime($value)); } return $el; } } } ?>
I decided to keep your current logic (using date_diff), but I thought that in the future you might have your boss telling you: “You know what? I don’t want to have Mondays there”, so with the current system you will have to manually edit your function and you may no longer remember what you did.
The class above expects four parameters:
- dateStart (dmY format)
- dateEnd (dmY format)
- daysToExclude (array with day identifiers to exclude -> array example (0.6) to exclude Saturday and Sunday).
- dateToExclude (an array with dates for exceptions, each supported format).
The class will automatically correct the format of the dateToExclude array so that you can use date_diff.
Here is a usage example, following your case:
<?php $dateStart = "01-05-2015"; $dateEnd = "01-06-2015"; $daysToExclude = array(0,6); $exclusions = array( "1-05-2015", "2-05-2015", "4-05-2015", "5-05-2015", "7-05-2015", "8-05-2015", "9-05-2015", "11-05-2015", "12-05-2015", "14-05-2015", "15-05-2015", "16-05-2015", "18-05-2015", "19-05-2015", "21-05-2015", "22-05-2015", "23-05-2015", "25-05-2015", "26-05-2015", "28-05-2015", "29-05-2015", "30-05-2015" ); $dateRange = new dateRange($dateStart, $dateEnd, $daysToExclude, $exclusions); echo $dateRange->getRangeLength(); ?>
The code above produces 5.
The getRangeLength function also takes a callback and returns an array result of the date_diff operation, so you can also:
$dateRange->getRangeLength(function($res) { echo "Literal output: <br />"; print_r($res); echo "<br />count is: " . count($res); });
The above outputs:
Literal output: Array ( [3] => 06-05-2015 [8] => 13-05-2015 [13] => 20-05-2015 [18] => 27-05-2015 [21] => 01-06-2015 ) count is: 5
So, if you later also need to remove Mondays, you can easily do this by changing daysToExclude to array(0,1,6);
I hope this will be useful for everyone who needs it, despite the fact that a valid answer has already been posted.
In any case, your original problem was largely related to the array_diff function, which did NOT do its job because the date strings were incompatible, because "01-01-2015" differs from "01-01-2015" if you do not first convert them to time, and then back to dates.