I need to generate multiple dates between two dates, based on an interval (eg. weekly, every 2 weeks, monthly, …), but I only need the ones in the future.
For that I’m using the Carbon 2.72.3 library and I came up with the following code:
$interval = CarbonInterval::week();
$startDate = Carbon::create(2024, 3, 17);
$endDate = Carbon::create(2024, 4, 1);
$amount = 4;
$period = CarbonPeriod::interval($interval)
->setStartDate($startDate)
->addFilter(fn(Carbon $carbon) => $carbon->isFuture(), 'isFuture')
->addFilter(fn(Carbon $carbon) => !$endDate || $carbon->isBefore($endDate))
->setRecurrences($amount);
dd($period->toArray());
Unfortunately, this just works sometimes (meaning: Not with all dates / intervals) and I can’t tell exactly under what conditions it works and when it doesn’t work.
With the dates above, Carbon throws an CarbonExceptionsUnreachableException
with the message Could not find next valid date.
. If I reduce the amount to 1, it works, but only returns 2024-03-24 as a date (which is then expected, but doesn’t solve my issue).
With other data, such as this, it works as expected: It returns 4 dates according to the interval in relation to the start date, but only the ones in the future.
$interval = CarbonInterval::month();
$startDate = Carbon::create(2022, 6, 2);
$endDate = null;
$amount = 4;
If I set the $endDate = Carbon::create(2024, 4, 1);
, it also stops working. I suspect that it sometimes happens when it cannot generate the $amount
of dates. But this doesn’t seem to be the case always, as the following setup should be able to generate at least 4 dates, though the same exception is thrown:
$interval = CarbonInterval::year();
$startDate = Carbon::create(2022, 6, 2);
$endDate = Carbon::create(2028, 4, 1);
$amount = 4;
Expected dates:
- 2024-06-02
- 2025-06-02
- 2026-06-02
- 2027-06-02
Though in this case it only works if I set the end date to 2029-04-01, which doesn’t make sense to me as the last date is already in 2027.
2
Answers
The syntax you’re using looks a bit complicated to me, and if you’re having trouble with it, maybe something simpler will work. The docs show pretty simple syntax for
CarbonPeriod
:And produces your expected output:
To set the end date, Carbon provides the
setEndDate()
method, so your code should be like this:Note that
setEndDate()
accepts anull
value.