too long

I have this function :

         function dateCalculator ($date, $frequency, $duration) {
$startingDate = $date;
$day = $startingDate->format('d');
$startingDate->setDate($startingDate->format('Y'), $startingDate->format('m'), 1);

for ($i = 0; $i < $duration; $i++) {

  $startingDate->modify("+{$frequency} month");

  echo $startingDate->format('t') < $day ? $startingDate->format('Y-m-t') : $startingDate->format('Y-m-' . $day);
  echo '<br />';
}

}//end of function

$date = new DateTime('2000-01-31');
dateCalculator($date, 1, 30);

This function adds any amount of months to date. The specific is that it adds date not in standard PHP format, but for example

Starting date : 30/01/2000 +1 month = 29/02/2000 +2 months= 30/03/2000

Starting date : 31/01/2000 +1 month = 29/02/2000 +2 months= 31/03/2000 +3 months= 30/04/2000 +5 months= 31/05/2000

and so on. This function is working good, you can check it on Online Compiler.

Now, I have a project where I have a function that calculates a lot of things, and do it in this way :

public function constantAmortization($date, $capital, $rate, $duration, $frequency, $charges)
    {
$this->array[$i] = array(
                          'Date' => $date->format('d/m/y'),//DATE
                          'Capital' => $capital,
                          'Rate' => $rate,
                          'Interest' => $interest,
                          'Payment' => $payment,
                          'Amortization' => $amortization,
                          'Remaining' => $remaining,
                          'InterestTotal' => $interestTotal,
                          'AmortizationTotal' => $amortizationTotal,
                          'PaymentTotal' => $paymentTotal,
                          'InverseCapital' => $inverseCapital,
                      );

              $capital = $remaining;
             // $months = (12/$frequency). ' months';
             // $date->modify($months); !it was before, but it gives me dates that i didn't want, like from 31/01/2010 to 02/03/2010.
              $this->dateCalculator($date,12/$frequency,$duration);

This function on each iteration makes new calculations, and fill the array that is outputed in front-end. So, number of iterations is $duration , 12/$frequency is how much months to add to date, $date is DataTime object that came from function parameter.

Also, to this class, below the function I added the public keyword to function, and instead of echo I put return, so it looks now :

 public function dateCalculator ($date, $frequency, $duration) {
 $startingDate = $date; // or whatever
 $day = $startingDate->format('d');
 $startingDate->setDate($startingDate->format('Y'), $startingDate->format('m'), 1);

  for ($i = 0; $i < $duration; $i++) {
    $startingDate->modify("+{$frequency} month");
      return $startingDate->format('t') < $day ? $startingDate->format('Y-m-t') : $startingDate->format('Y-m-' . $day);
  }//for

}//end of function

But the results that came from this function that is kind of identic... is Starting date : 31/08/2010, add 1 month 50 times. Next iteration : 01/09/2010 that is already not correct, at online compiler it gives all right, like 31/08/2010, 30/09/2010, 31/10/2010, 30/11/2010, 31/12/2010, 31/01/2011, 28/02/2011...

What is wrong ? :/

EDIT : I observe that if I put a date of 20/02/2000 and add 1 month, anyway, next date is 01/03/2000, (first date of next month). But why it happens?) And after that, any next iteration is with date 1. 01/04/2000, 01/05/2000 ... So, the first iteration fails, it produce all fail like domino principle

Something was not OK when iterating. So, now, when the function is called inside a for loop to change the date on each iteration, the following function is working in the right way.

This code adds any amount of months to the date in a specific mode : First case : If starting date DAY = Number of days in this month Second case : If starting date DAY is not equal Number of days in month, but is greater or equal then 28 Third case : If starting date DAY is less then 28

Suppose we have a function where we have declared a $date variable in some format. Now, we have to decide what case we have to apply. Use this code :

if ($date->format('d') == $date->format('t')) {
      $case = 1; $day = $date->format('d'); } 
    if ($date->format('d') != $date->format('t') && $date->format('d') >= 28) {
      $case = 2; $day = $date->format('d'); }
    if ($date->format('d') != $date->format('t') && $date->format('d') < 28){
      $case = 3; $day = $date->format('d'); } 

Next, just use this function. $date parameter is the curent (initial) date. $day is determined in previous if statements (number of day from starting date), $M is how much months to add to this date and $case came from previous if statements that determines which algorithm branch to use.

function dateCalculator($date, $day, $M, $case){
//case1 => day is last day of the month
//case2 => day is not last day of the month, but is 28+
//case3 => day is less then 28
//M = 12/frequency 
              if($case == 1) {
              $date->modify('last day of next month');
              }//case1

             if($case == 2 && $M == 1) {
              $date->modify('first day of next month');
                if($day > $date->format('t')){
                  $date->modify('last day of this month');}
                if($day < $date->format('t')) {
                  $date->modify('last day of this months');
                  $temp = $date->format('t') - $day;
                  $date->modify('-' . $temp . ' days');
                }
                if($day == $date->format('t')) {
                  $date->modify('last day of this month');
                }
             }//case2 M 1

              if($case == 2 && $M != 1) {
                $date->modify('first day of ' . $M . ' months');
                  if($day >= $date->format('t')) {
                    $date->modify('last day of this month');
                  } else {
                  $date->modify('last day of this months');
                  $temp = $date->format('t') - $day;
                  $date->modify('-' . $temp . ' days');
                  }
             } //case 2 M <>

             if($case == 3) {
              $date->modify('+ ' . $M . ' months');
             }//case3

}//end of function