Search code examples
phparraysdatedaysmonthcalendar

get between two date all days for every Month in PHP


How i can to get all days for every Month between two days in array like this

$dateStart = "2016/12/14"; 
$dateFin =   "2017/04/21"

[2016/12/14 - 2016/12/31] => 17 days
[2017/01/01 - 2017/01/31] => 31 days
[2017/02/01 - 2017/02/28] => 28 days
[2017/03/01 - 2017/03/30] => 31 days
[2017/04/01 - 2017/04/21] => 21 days

Solution

  • You can use the function cal_days_in_month plus DateTime class:

    <?php
    $dateStart = new DateTime("2016/12/14");
    $dateFin = new DateTime("2017/04/21");
    $firstDay = $dateStart->format('Y/m/d');
    $lastDay = $dateStart->format('Y/m/t');
    $totalMonths = $dateStart->diff($dateFin)->m + ($dateStart->diff($dateFin)->y*12);
    $result = [];
    for ($i = 0; $i <= $totalMonths; $i++)
    {
        if ($i != 0){
            $dateStart->modify('first day of next month');
            $firstDay = $dateStart->format('Y/m/d');
            $dateStart->modify('last day of month');
            $lastDay = $dateStart->format('Y/m/t');
        }
    
        $nextDate = explode('/', $firstDay);
    
        $totalDays = cal_days_in_month(CAL_GREGORIAN, $nextDate[1], $nextDate[2]);
        if ($i == 0){
            $totalDays -= $dateStart->format('d');
        } else if ($i == $totalMonths) {
            $totalDays = $dateFin->format('d');
        }
    
        $result["$firstDay - $lastDay"] = $totalDays;
    }
    
    var_dump($result);
    

    Lacks improvement, but gives what you asked.

    Routine Improved, check below:

    $dateStart = new DateTime("2016/12/14");
    $dateFin = new DateTime("2017/04/21");
    $totalMonths = $dateStart->diff($dateFin)->m + ($dateStart->diff($dateFin)->y*12);
    $result = [];
    for ($i = 0; $i <= $totalMonths; $i++)
    {
        if ($i != 0){
            $obj = $dateStart->modify('first day of next month');
        }
    
        $firstDay = $dateStart->format('Y/m/d');
        if ($i == $totalMonths){
            $lastDay = $dateFin->format('Y/m/d');
        } else {
            $lastDay = $dateStart->format('Y/m/t');
        }
        $firstDayObj = strtotime($firstDay);
        $lastDayObj = strtotime($lastDay);
        $totalDays = (int) ceil(($lastDayObj - $firstDayObj) / 86400);
        $totalDays = ((int) $dateStart->format('d') == 1) ? $totalDays + 1 : $totalDays;
        $result["$firstDay - $lastDay"] = $totalDays;
    }
    
    var_dump($result);
    
    //array(5) { ["2016/12/14 - 2016/12/31"]=> int(17) ["2017/01/01 - 2017/01/31"]=> int(31) ["2017/02/01 - 2017/02/28"]=> int(28) ["2017/03/01 - 2017/03/31"]=> int(31) ["2017/04/01 - 2017/04/21"]=> int(21) }