I've been looking for a way to accurately calculate the next/future billing date in a way that a month will not be skipped. For example for Jun 31 I want the next billing date to be Feb 28 (or 29 when applicable). I found this great solution. Here is an update of that code to support more than 1 month in the future. Hope that helps.
Code:
function calculateBillingDate($startDate, $numberOfCycles = 1) {
$currentMonth = date('n', $startDate);
$nextMonth = (($currentMonth + $numberOfCycles) % 12);
if ($nextMonth === 0) {
$nextMonth = 12;
}
$targetDate = new \DateTime();
$targetDate->setTimestamp($startDate);
$targetDate->add(new \DateInterval('P' . $numberOfCycles . 'M'));
while ((int)$targetDate->format('m') !== $nextMonth) {
$targetDate->sub(new \DateInterval('P1D'));
}
return $targetDate;
}