Using Carbon to generate multiple dates with an interval in a range, but only ones in the future

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.