I have a calendar application which utilizes the newer PHP DateTime classes. I have a way that I handle recurring events, but it seems hack-ish and I wanted to see if you guys h
This can be done nicely using a DatePeriod as an Iterator and then filterd to the start date you want to display:
<?php
class DateFilterIterator extends FilterIterator {
private $starttime;
public function __construct(Traversable $inner, DateTime $start) {
parent::__construct(new IteratorIterator($inner));
$this->starttime = $start->getTimestamp();
}
public function accept() {
return ($this->starttime < $this->current()->getTimestamp());
}
}
$db = new DateTime( '2009-11-16' );
$de = new DateTime( '2020-12-31 23:59:59' );
$di = DateInterval::createFromDateString( '+3 days' );
$df = new DateFilterIterator(
new DatePeriod( $db, $di, $de ),
new DateTime( '2009-12-01') );
foreach ( $df as $dt )
{
echo $dt->format( "l Y-m-d H:i:s\n" );
}
?>
You could format your date as a unix timestamp then use modular division to find the first instance in the selected month, then step in increments of 3 days from there. So for your example:
$startDate = new DateTime(20091116);
$startTimestamp = $startDate->format('u');
$recursEvery = 259200; // 60*60*24*3 = seconds in 3 days
// find the first occurrence in the selected month (September)
$calendarDate = new DateTime(31000901); // init to Sept 1, 3100
while (0 != (($calendarDate->format('u') - $startTimestamp) % $recursEvery)) {
$calendarDate->modify('+1 day');
}
$effectiveDates = array();
while ($calendarDate->format('m') == 9) {
$effectiveDates[] = clone $calendarDate;
$calendarDate->modify('+3 day');
}
//$effectiveDates is an array of every date the event occurs in September, 3100.
Obviously, you've got a few variables to swap out so the user can select any month, but that should be the basic algorithm. Also, ensure your DateTimes are the correct date, but with the time set as 00:00:00, or else the first while loop will never resolve. This also assumes you've ensured the selected date is later than the beginning date of the event.