Question

How do I check if the date ranges overlaps? I have this in my model, it keeps saving.

public function dateRangeExists($attribute, $params) {
    $criteria = new CDbCriteria;

    $criteria->compare('id_one',$this->id_one,true,);
    $criteria->compare('id_two',$this->id_two,true,'OR');
    // $criteria->addCondition('start_date < '.$this->start_date);
    // $criteria->addCondition('end_date > '.$this->end_date);

    $criteria->addBetweenCondition('start_date', $this->start_date, $this->end_date);
    $criteria->addBetweenCondition('end_date', $this->start_date,$this->end_date);

    $record = self::model()->exists($criteria); 

    if(!empty($record)) {
         $this->addError('id', 'Item already exists within range.');
         return false;
    }
}
Was it helpful?

Solution

There are 3 possible scenarios for event overlap:

  1. An event started before the current event (end date is after current event start date)
    enter image description here

  2. An event started while the current event is going on (start date is before current event end date)
    enter image description here

  3. An event starts and ends during the current event (can be ignored as either rule above still applies)
    enter image description here

As described above, what you need to do have a condition to check if an existing event exists where the end date is after current start date (#1), OR start date is before current end date (#2). Notice the use of the keyword OR:

WHERE (start_date < $this->start_date AND end_date > $this->start_date)
OR (start_date < $this->end_date AND end_date > $this->end_date)

To apply this to Yii context, I would do it this way:

$criteria = new CDbCriteria;
$criteria->addCondition(
    "WHERE (end_date > '{$this->start_date}' OR start_date < '{$this->end_date}')".
    "OR (start_date < '{$this->end_date}' AND end_date > '{$this->end_date}')"
);

I would also additionally use a visual calendar on the client-side to block off dates that already have an event, to avoid user selecting those dates.

If you are using jQueryUI, here's an existing solution: jquery UI datepicker - disabling date ranges

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top