Skip to content

Instantly share code, notes, and snippets.

@Horat1us
Last active January 10, 2019 16:22
Show Gist options
  • Save Horat1us/76f7e33b8d217ddb929bbf1dae668e4a to your computer and use it in GitHub Desktop.
Save Horat1us/76f7e33b8d217ddb929bbf1dae668e4a to your computer and use it in GitHub Desktop.
PHP Generate month period using Carbon

Description

Generating series of months between two dates.

Requirements

Dependency: nesbot/carbon PHP: >=7.0

Source Code

Array Return

<?php

use Carbon\Carbon;

function generatePeriod(Carbon $dateStart, Carbon $dateEnd): array
{
    /** @var Carbon[][] $period */
    $period = [
        [
            'start' => $dateStart->copy(),
            'end' => min($dateStart->copy()->endOfMonth(), $dateEnd),
        ],
    ];
    $last = $period[0];

    while ($last['end'] < $dateEnd) {
        $month = $last['start']->copy()->startOfMonth()->addMonth();

        $period[] = $last = [
            'start' => $month->copy(),
            'end' => min($month->copy()->endOfMonth(), $dateEnd)
        ];
    }

    return $period;
}

Generator

<?php

use Carbon\Carbon;

function generatePeriod(Carbon $dateStart, Carbon $dateEnd): \Generator
{
    /** @var Carbon[] $last */
    $last = [
        'start' => $dateStart->copy(),
        'end' => min($dateStart->copy()->endOfMonth(), $dateEnd),
    ];
    yield $last;

    while ($last['end'] < $dateEnd) {
        $month = $last['start']->copy()->startOfMonth()->addMonth();

        $last = [
            'start' => $month->copy(),
            'end' => min($month->copy()->endOfMonth(), $dateEnd)
        ];
        yield $last;
    }
}

Usage

Source

<?php

use Carbon\Carbon;


function displayPeriod(Carbon $dateStart, Carbon $dateEnd): void
{
    $period = generatePeriod($dateStart, $dateEnd);

    echo "Period between {$dateStart->toDateTimeString()} and {$dateEnd->toDateTimeString()}\n";

    /**
     * @var Carbon $start
     * @var Carbon $end
     */
    foreach ($period as ['start' => $start, 'end' => $end]) {
        echo "{$start->toDateTimeString()} -> {$end->toDateTimeString()}\n";
    }
    echo "\n";
}

$dateStart = Carbon::parse('2018-10-05');
$dateEnd = Carbon::parse('2018-12-04');

displayPeriod($dateStart, $dateEnd);

$dateStart = Carbon::parse('2018-10-05');
$dateEnd = Carbon::parse('2018-10-21');

displayPeriod($dateStart, $dateEnd);

Output

Period between 2018-10-05 00:00:00 and 2018-12-04 00:00:00
2018-10-05 00:00:00 -> 2018-10-31 23:59:59
2018-11-01 00:00:00 -> 2018-11-30 23:59:59
2018-12-01 00:00:00 -> 2018-12-04 00:00:00

Period between 2018-10-05 00:00:00 and 2018-10-21 00:00:00
2018-10-05 00:00:00 -> 2018-10-21 00:00:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment