-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
"Inverted" CarbonPeriod with custom CarbonInterval #3070
Comments
Hello, step interval are a bit special because they can be either positive or negative, in a non-predictible way, the order can even be variable: $i = 0;
$period = CarbonPeriod::create('2024-09-11', 4, static function (CarbonInterface $date) use (&$i): CarbonInterface {
return match(++$i) {
1 => $date->addDay(),
2 => $date->subDays(2),
3 => $date->addDays(3),
default => $date,
};
}); Will result in:
As you correctly found out, currently the direction of the period is driven by the interval (assumed descending if inverted, else ascending). The logic for that is here: So instead of $twoWeekdaysInterval->invert($endDate < $startDate); At the moment, that the cleanest way I can found. You can also completely replace the filters of the period (which decide when to stop iterating), that is the more "correct" way but the verbosity of it is likely not worth it. $descending = ($endDate < $startDate);
$twoWeekdaysPeriod = CarbonPeriod::create($startDate, $endDate, function (CarbonInterface $date) use ($descending): CarbonInterface {
return $descending
? $date->subWeekdays(2)
: $date->addWeekdays(2);
})->setFilters([
[function (CarbonInterface $date) use ($endDate, $descending): bool|callable {
return ($descending
? ($date > $endDate)
: ($date < $endDate)
) ?: CarbonPeriod::END_ITERATION;
}, null]
]);
// Here you'll get your 3 dates
echo "twoWeekdaysPeriod: {$twoWeekdaysPeriod->count()}\n";
foreach($twoWeekdaysPeriod as $date) {
echo $date->toDateString();
echo "\n";
} |
Thank you. I have chosen the following option. Works for both reverse and normal periods. //reverse period
$startDate = Carbon::create('2024-09-12')->startOfDay();
$endDate = Carbon::create('2024-09-5')->startOfDay();
//normal period
//$startDate = Carbon::create('2024-09-5')->startOfDay();
//$endDate = Carbon::create('2024-09-12')->startOfDay();
$descending = ($endDate->lessThan($startDate));
$twoWeekdaysInterval = new CarbonInterval(function(CarbonInterface $date, bool $negated) use($descending): DateTime {
return $descending
? $date->subWeekdays(2)
: $date->addWeekdays(2);
});
$twoWeekdaysInterval->invert($descending);
$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>";
} However, it would be good if the closure was also passed the appropriate $negated (if inverted, TRUE). Then there is no need for tricks with 'use($descending)'. |
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:
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:
I tried to trick and always subtract in closure and this works:
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!
The text was updated successfully, but these errors were encountered: