Do not show list items (dates) which are older than today


i have a list of date items and want to exclude items from the list which have a date older than today. How can i do this? Should be a simple if-clause, but i am a beginner at PHP. Can anybody help me, what and where to put in the controller to make it work?

Here is the controller i use:


return function($site, $pages, $page) {

  // fetch the basic set of pages
  $dates = $page->children()->visible()->sortBy('date_start');

  // add the tag filter
  if($tag = param('category')) {
    $dates = $dates->filterBy('category', $tag, ',');

  // fetch all tags
  $categories = $dates->pluck('category', ',', false);

  // apply pagination
  $dates   = $dates->paginate(10);
  $pagination = $dates->pagination();

  return compact('dates', 'category', 'tag', 'pagination');


return function($site, $pages, $page) {

    $tag = urldecode(param('category'));
    if($tag) {
    	$dates = page('dates')->children()->visible()->filterBy('category', $tag,',')->sortBy('date_start');
    } else {
    	$dates = page(dates')->children()->visible()->sortBy('date_start');

     return compact('dates');


Why do you have two controllers?

To filter by a custom date field (i.e. a field that is not called date), you can use the filter($callback)method like this:

$dates = $page->children()->visible()->filter(function($child) {
            return $child->date(null, 'date_start') >= time();

Double arrow typo…

Corrected, tack :slight_smile:

Thanks for the code and typo tip!

Second controller seems to be a relict from “cut & paste”… just deleted it.

It nearly works now, except todays dates (appointment items) will not show up, only from following day. Any ideas?

Not tested, but try to pass a format:

$dates = $page->children()->visible()->filter(function($child) {
            return $child->date('Y-m-d', 'date_start') >= time();

Unfortunately it does not work.

In config.php i changed the date-handler to
c::set('date.handler', 'strftime');

Can the issue be associated with this?

That may well be, try if it works if you comment out the config item.

Just tried it.
It did not change anything (except my dates look pretty ugly now).

Ok, this should work now:

$dates = $page->children()->visible()-> ->filter(function($child) {
  return $child->date('Ymd', 'date_start') >= date('Ymd');

Now older dates than today show up again! (Sorry. I really appreciate your support!)
Do you have another idea?

I tested this in a Starterkit, maybe the name of the field is wrong, I used start_date in my code above instead of date_start?

Filtering works now when i comment this out in config.php
/* c::set('date.handler', 'strftime'); */

But then i get problems with my date formatting. I need day names (Mon-Sun), days (01-31), month names (Jan-Dez) and year (2016 e.g.) from a custom date field.

With strftime i do this:

<span class="rd-dayname"><?php echo $single-date->date('%a', 'date_start'); ?></span>
<span class="rd-day"><?php echo $single-date->date('%d', 'date_start'); ?></span>
<span class="rd-month"><?php echo $single-date->date('%b', 'date_start'); ?></span>
<span class="rd-year"><?php echo $single-date->date('%G', 'date_start'); ?></span>

I did not manage to do this with the standard date handler.

Is there a way to do this without switching to “strftime”?

I use in such situations the following code in the snippets or templates:

<?php echo utf8_encode (strftime("%A, %d. %B %Y", $page->thedate())) ?>

if $page->thedate() is the field with the date and %A, %d. %B %Y are the details, I want to show.

Good luck!

Please note that you can’t pass the field object as second parameter to the strftime function, but have to convert it to long first:

<?= strftime("%A, %d. %B %Y", strtotime($page->date_start())) ?>

Depending on the language you need, you might have to set the locale in your config.php, e.g.

c::set('locale', array(
  LC_ALL => 'de_DE'

Edit: Or in your example:

<span class="rd-dayname"><?= strftime("%a", strtotime( $single-date->date_start())) ?></span>
<span class="rd-day"><?= strftime("%d", strtotime( $single-date->date_start())) ?></span>
<span class="rd-month"><?= strftime("%b", strtotime( $single-date->date_start())) ?></span>
<span class="rd-year"><?= strftime("%G", strtotime( $single-date->date_start())) ?></span>
1 Like

Yay! Finally filtering works now! Thanks so much! I highly appreciate the support from all of you!

Only one little thing left:

For German March
<?= strftime("%b", strtotime( $single-date->date_start())) ?>
shows “M�R”

c::set('locale', array(LC_ALL => 'de_DE'));
is set in config.php

No problems with German umlauts in other Kirby fields. Just this custom date field.

Any ideas?

Found a solution which fixed the German umlauts problem:

c::set('locale', array(LC_ALL => 'de_DE.UTF-8'));

Thanks again!

Some hints from me:

If the panel field is defined like

    label: Datum
    type:  date

then I don’t need strtotime( ... ), but secure is secure and sometimes this is needed.
Thanks to @texnixe for her clue.

I run XAMPP on Windows as my development system.
Therefore I have to set something like

// set 'locale' to '' for Windows servers and to 'de_DE.utf8' for the rest
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN')
c::set('locale', '');
c::set('locale', 'de_DE.utf8');

because the webserver “Apache on Windows” (e.g. XAMPP) needs an empty string for the locale. Every Apache on Windows uses the defaults for this from the operating system of the webserver (Apache)!

Therefore I use utf8_encode ( ... ) for the encoding of the German Umlauts (e.g. ä, ö, ü) to UTF8 to avoid [quote=“rene, post:16, topic:5858”]


Good luck!

And this runs on linux servers without any change like
Veröffentlicht am Freitag, 25. März 2016

Thanks for the additional hints.
This will be helpful for my development system as well!


1 Like