将PHP脚本转换为通用案例函数

I have this code that modify date in the way I want, for example, if starting date is 31/01/2000, adding 1 month will return 29/02/2000, then, 31/03/2000. If date is 30/01/2000 (not last day of the month) it will return 29/02/2000, then 30/03/2000, 30/04/2000 and so on.

I want to transfirm that code in a general case function, to be able to add 1,3,6,12 months, and inside the for loop, to work all corect. I would like it to be a function 2 or 3 arguments, startingDate, duration(nr of iterations), frequency (add 1/3/6/12 months per once).

   <?php
$date = new DateTime('2000-01-28'); // or whatever
#echo $date->format('d')." ".$date->format('t');
$expectedDay = $date->format('d');
$month = $date->format('m');
$year = $date->format('Y');

for ($i = 0; $i < 100; $i++) {
    echo $date->format('Y-m-d')  . "<br>"; 
    if ($month++ == 12) {
        $year++;
        $month = 1;
    }

    $date->modify("${year}-${month}-1");
    if ($expectedDay > $date->format('t')) {
        $day = $date->format('t');
    } else {
        $day = $expectedDay;    
    }
    $date->modify("${year}-${month}-${day}");
}       

Whelp, there's an extremely easy function for this in PHP nowadays.

first, you get a timestamp instead of a datetime:

$timestamp = $date->getTimestamp();

Now, just use strtotime to add onto the date.

strtotime("+1 month", $myTimestamp);

You can change the +1 into anything you want, so you just throw the amount in the string and voila; a dynamic way of adding them!

however, since you want to do +30 days instead of a natural month, you're better off just adding 30 days to the timestamp, like so:

$timestamp = $timestamp + (3600 * 24 * 30); //s per h * h per d * d

So, you'd end up with something like this:

function calculateTime($startingDate, $iterations, $frequency){
    $timeStamp = strtotime($startingDate);//if you expect a string date
    $timeToAdd = (3600 * 24 * 30) * $frequency; //30 days * frequency
    $return = array();
    $return[] = date('Y-m-d', $timeStamp); //Original date
    $previousDate = $timeStamp; //Original date  for now
    for($i = 0; $i < $iterations; $i++){
        $newDate = $previousDate + (3600 * 24 * 30);
        $return[] = date('Y-m-d', $newDate);
        $previousDate = $newDate;
    }
    return $return;
}

And then for the rendering part:

//Let's render this stuff
$dates = calculateTime('24-08-2017', 25, 3);
foreach($dates as $date){
    echo "$date</br>";
}

If you'd like to do it with full months, something like this:

<?php
function calculateTime($startingDate, $iterations, $frequency){
    $timeStamp = strtotime($startingDate);//if you expect a string date
    $return = array();
    $return[] = date('Y-m-d', $timeStamp); //Original date
    $previousDate = $timeStamp; //Original date  for now
    for($i = 0; $i < $iterations; $i++){
        $lastDay = false;
        //It's the last day of the month
        if(date('t', $timeStamp) == date('d', $timeStamp)){
            $lastDay = true;
        }        
        if($frequency == 12){
            $newDate = strtotime('+1 year', $previousDate);  
        }
        else{
            if($lastDay){
                $firstDayOfMonth = strtotime(date("01-m-Y", $previousDate));
                $newDate =strtotime("+$frequency month", $firstDayOfMonth);
            }
            else{
                $newDate = strtotime("+$frequency month", $previousDate);
            }
        }
        if($lastDay){
            $return[] = date('Y-m-t', $newDate);
        }
        else{
            $return[] = date('Y-m-d', $newDate);
        }
        $previousDate = $newDate;
    }
    return $return;
}
//Let's render this stuff
$dates = calculateTime('31-01-2000', 25, 1);
foreach($dates as $date){
    echo "$date</br>";
}

I hope this helps? :)

If you'd like to see how this works quickly, just paste my code into a phpfiddle. Unfortunately the save function is broken right now.