Search code examples
phplistdatedatetimesequential

Create a list of sequential monthly dates in PHP given initial date and quantity


I'm working on a little payments system and must generate a list of payment days (monthly) given an initial date and number of payments. So, for example:

Given:

startday: 2015/06/22
qtty: 6

I should get the day from initial date (22) and generate a list of 6 sequential monthly dates:

  • 2015/06/22 (if initial date should be included, and is > than today)
  • 2015/07/22
  • 2015/08/24
  • 2015/09/22
  • 2015/10/22
  • 2015/11/23

As you can see, generated dates should not be weekends (sat/dom) and -if possible- nor holidays

Is there any function that could help me achieve this? TIA


Solution

  • I think this might do what you want, including holidays:

    <?php
    
    $startday = strtotime("2015/08/24");
    $qtty = 5;
    
    // Add as many holidays as desired.
    $holidays = array();
    $holidays[] = "4 Jul"; 
    $holidays[] = "25 Dec";
    
    
    for( $i = 0; $i < $qtty; $i++ ) {
        $next_month = strtotime("+".$i." month", $startday); // Also works with "+ 30 days"
        while( in_array(date("d M", $next_month), $holidays)) { // Is holiday
            $next_month = strtotime("+ 1 day", $next_month);
    
            if( date("N", $next_month) > 5 ) { // Is weekend
                $next_month = strtotime("next Monday", $next_month); // or "previous Friday"
            }
       }
        echo(date( "Y-m-d", $next_month) . '</br>');
    }
    
    ?>
    

    Will echo

    2015-08-25
    2015-09-25
    2015-10-26 // Because of weekend
    2015-11-25
    2015-12-28 // Because of Christmas and weekend
    

    And with a start date of 2015/10/31 the output will be:

    2015-11-02 // Because of weekend
    2015-12-01 // Because the 31st of Nov is the 1st of Dec
    2015-12-31
    2016-02-01 // Because the weekend
    2016-03-02 // Because the 31st of Feb is the 2st of Mars (as 2016 is leep year)
    

    As a good extra tips, depending on how you want to solve the 31st of Jan problem, if you want the last of each month, you can always use the following:

    $first_of_the_month = strtotime(date("Y-m-1", $startday));
    $next_month = strtotime("+ 1 month", $first_of_the_month);
    $last_of_the_month = date("Y-m-t", $next_month);
    echo($last_of_the_month); // 2015-09-30