Create a collection of dates based on current day

Hi dear community,

I’ve recently created a sort of calendar that displays only dates extracted from a collection of upcoming events. Everything works as expected, but my client finally wants to show 90 days (3 month) in this calendar, even if no events are scheduled :exploding_head:

Currently, dates are stored in each event page in a structure field that looks like:

dates:
  type: structure
  fields:
    day:
      type: date
      display: DD/MM/YYYY
    hour:
      type: time
      display: H:mm

And all dates of all events are merged in a collection this way (which is later grouped, filtered, etc):

$alldates = new Collection();
foreach($kirby->collection('events') as $event){
  $alldates->add($event->dates()->toStructure()->filter(function ($item) {
    return $item->hour()->isNotEmpty() && $item->day()->toDate('%F') >= date('Y-m-d');
  }));
}

Do you know how I can replace the foreach loop above so the $alldates collection contains 90 days starting from today, without changing how dates are currently stored/structured?

Thank you all for your help :pray:

You can use the DateTime class, in particular DateInterval to create a 90 day period. The you can check for each day if events exist.

https://www.php.net/manual/en/class.dateinterval.php

How useful that is to print days without events (if you don’t print something that actually resembles a calendar)

Hi pixelijn, and thanks for your time!

My current logic is as follow:

  1. Create a collection of days based on upcoming events
  2. Group the days per month
  3. Split the days in 4 time slots
  4. For each time slot, filter the events collection and display the event(s) scheduled

This is probably not the nicest way to do it but it works. In order to avoid rewriting all my loops/conditions/filters in steps 2, 3, 4, I thought a solution would be to update only the first step, so the $alldates collection stores 90 dates starting from today.

Does that make more sense? :sweat_smile:

I played around with dateInterval as suggested and here is the final working code, for reference:

$alldates = new Collection();
$today = new DateTime();
$end = new DateTime();
$end->add(new DateInterval('P3M'));
$period = new DatePeriod($today, DateInterval::createFromDateString('1 day'), $end);
foreach ($period as $id => $day) {
  $seances->add(new Kirby\Cms\StructureObject([
    'id' => $id,
    'content' => [
      'day' => $day->format("Y-m-d"),
      'hour' => ''
    ]
  ]));
}

Thanks for your help pixelijn :blush: