Skip to content

"Inverted" CarbonPeriod with custom CarbonInterval #3070

@eddi13

Description

@eddi13

Hello.

Carbon version: 3.8.0

PHP version: 8.2.23

I would like to get a period in "reverse" order (start date is greater than end date).
In "normal" cases it works:

$startDate = Carbon::create('2024-09-12')->startOfDay();
$endDate = Carbon::create('2024-09-5')->startOfDay();

$twoDaysInterval = new CarbonInterval();
$twoDaysInterval->subDays(2);
$twoDaysPeriod = $twoDaysInterval->toPeriod($startDate, $endDate);//works: 2024-09-12, 2024-09-10, 2024-09-08, 2024-09-06
echo "twoDaysPeriod: {$twoDaysPeriod->count()}<br>";
foreach($twoDaysPeriod as $date) {
	echo $date->toDateString();
	echo "<br>";
}

But I need a customized CarbonInterval because I have to subtract the working days.
The closure does not work properly because $negated is always passed as FALSE (is a bug?). Regardless of whether CarbonInterval is inverted or not:

$startDate = Carbon::create('2024-09-12')->startOfDay();
$endDate = Carbon::create('2024-09-5')->startOfDay();

$twoWeekdaysInterval = new CarbonInterval(function (CarbonInterface $date, bool $negated): DateTime {
    // $negated is true when a subtraction is requested, false when an addition is requested
    return $negated
        ? $date->subWeekdays(2)
        : $date->addWeekdays(2);
});
$twoWeekdaysInterval->subDays(1);//is inverted
$twoWeekdaysPeriod = $twoWeekdaysInterval->toPeriod($startDate, $endDate);//not works
//ErrorException: E_WARNING: DateTime::modify(): Failed to parse time string (10000-01-04 00:00:00.000000) at position 12 (0): Double time specification inc\vendor\Carbon\src\Carbon\Traits\Modifiers.php [442]
echo "twoWeekdaysPeriod (uses 'negated'): {$twoWeekdaysPeriod->count()}<br>";
foreach($twoWeekdaysPeriod as $date) {
	echo $date->toDateString();
	echo "<br>";
}

I tried to trick and always subtract in closure and this works:

$startDate = Carbon::create('2024-09-12')->startOfDay();
$endDate = Carbon::create('2024-09-5')->startOfDay();

$twoWeekdaysInterval = new CarbonInterval(function (CarbonInterface $date, bool $negated): DateTime {
   return $date->subWeekdays(2);
});
$twoWeekdaysInterval->subDays(1);
$twoWeekdaysPeriod = $twoWeekdaysInterval->toPeriod($startDate, $endDate);//works: 2024-09-12, 2024-09-10, 2024-09-06
echo "twoWeekdaysPeriod: {$twoWeekdaysPeriod->count()}<br>";
foreach($twoWeekdaysPeriod as $date) {
	echo $date->toDateString();
	echo "<br>";
}

But I have the feeling that the code is not clean - it's a trick.
Maybe I'm thinking in the wrong direction.
What would be the "right" way to create such a "reverse" CarbonPeriod?

Thanks in advance!

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions