Generating series of months between two dates.
Dependency: nesbot/carbon
PHP: >=7.0
<?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;
}
<?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;
}
}
<?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);
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