PHP 5.3 DateTime for recurring events

后端 未结 2 802
孤街浪徒
孤街浪徒 2021-02-04 22:21

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

相关标签:
2条回答
  • 2021-02-04 22:32

    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" );
    }
    ?>
    
    0 讨论(0)
  • 2021-02-04 22:36

    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.

    0 讨论(0)
提交回复
热议问题