Yinelenen etkinlikler için PHP 5.3 DateTime

2 Cevap php

Ben yeni PHP DateTime sınıfları kullanan bir takvim uygulaması var. Ben yinelenen olayları işlemek için bir yol var, ama bu hack-ish görünüyor ve ben siz daha iyi fikirleri varsa görmek istedim:

  1. Ben 11/16/2009 (16 Kasım 2009) başlayan bir yinelenen olay var
  2. Bu 3 gün, her meydana gelecek
  3. Olay süresiz tekerrür edecek

Adlı kullanıcı Aralık, 3100 takvim bakar diyelim - bu olay normal gibi her 3 günde bir tekrarlanması orada göstermelidir. Soru - nasıl o gün o ayın hesaplanır?

=========================================

This is how I basically do it, but I know I'm missing something easier:

  1. Ben ay (1 Aralık 3100) baktı olmanın başlangıç ​​ve $ daysDiff gibi saklanan etkinlik başlangıç ​​tarihi (16 Kasım 2009) arasındaki gün farkı hesaplamak
  2. Ben bu gibi baştan 3 gün bir faktör olsun, böylece modülü çıkarma: $ daysDiff - ($ daysDiff% 3)
  3. Tartışmanın uğruna bir tarih olarak bana 29 Kas 3100 verir söylüyorlar sağlar.
  4. Ben Aralık 3100 içindeki tüm tarihleri ​​var kadar sonra tekrar tekrar bu tarihten 3 gün eklemek

My main problem comes with step 1. The PHP DateInterval::date_diff function does not calculate differences in days. It will give me years, months, ve days. I then have to fudge the numbers to get an estimate date around Dec, 3100. 11/16/2009 + (1090 years * 365.25 days) + (9 months * 30.5 days) + 15 days

Eğer 9999 yılı gibi geleceğe GERÇEK kadar gittiğinizde, bu tahmin sonra ben gereken yere almak için 3 gün aralıklarla bir sürü çıkarmak zorunda, bir ay kapalı olabilir.

2 Cevap

Bir unix zaman damgası oradan 3 gün artışlarla adım sonra, seçilen ayın ilk örneğini bulmak için modüler bölme kullanmak gibi sizin tarihi biçimlendirmek olabilir. Sizin Yani, örneğin:

$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.

Açıkçası, bu kadar kullanıcı herhangi ay seçebilirsiniz takas için birkaç değişken var, ama bu temel algoritma olmalıdır. Ayrıca, tarihsaat doğru tarih vardır, ancak döngü çözmek asla olurken zaman 00:00:00, yoksa ilk olarak ayarlandığında emin olun. Bu aynı zamanda, seçilen tarih daha sonra olayın başlangıç ​​tarihinden daha sağladık varsayar.

Bu DatePeriod bir Iterasyon olarak kullanarak güzel yapılır ve ardından görüntülemek istediğiniz başlangıç ​​tarihinden filterd edilebilir:

<?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" );
}
?>