2013-06-11 2 views
1

У меня есть приложение CakePHP, которое используется в качестве центра портала для повседневной деятельности нашей компании. Они состоят из различных систем бронирования и информации, таких как сотрудники и их отделы. Системные запуски CakePHP 2.2Разделительный диапазон дат за выходные

В настоящее время я внедряю систему, в которой лицо, проводящее тендер, может подать заявку на заключение контракта. Этот контракт имеет различные изменения, которые будут зависеть от того, как задолго до крайнего срока (тендера) проект контракта должен быть передан юридическому лицу, составить официальный контракт. Затем система «заказывает» юридическое лицо в течение нескольких дней, когда этот контракт устанавливается. В те дни никаких других заказов нельзя делать.

Система работает отлично, но она не расколола контракт на выходные. Он движется все дни до выходных. Скажем, ради аргументов, я заказываю проект контракта для завершения 18 июня. Система определяет, что общее время контракта составит 3 дня. Это означает, что контракт должен упасть за выходные, и он должен блокировать 13, 14 и 17 июня (а не 18-го, так как мне нужно иметь готовый документ к тому времени). ОДНАКО, система блокирует 12-14 июня.

Извините, что долго читал, но я бы предпочел, чтобы вы знали всю историю, а не просто кусочки. Вот мой код системы:

$tenderDocument = $this->TenderDocument->read(null,$id); 
$deadline = $tenderDocument['TenderDocument']['required_date']; 
$deadline = $start = date('Y-m-d',strtotime('-1 day',strtotime($deadline))); 
$start = date('Y-m-d',strtotime('-' . $tenderDocument['ContractForm']['time'],strtotime($deadline))); 
$dates[] = $current = $start; 
while($current < $deadline){ 
    $current = date('Y-m-d',strtotime('+1 day',strtotime($current))); 
    $dates[] = $current; 
} 
$is_available = array(); 
$is_available = $this->TenderDocument->find('first', 
    array(
     'conditions' => array(
      '(TenderDocument.start_date >= "' . $start . '" AND 
      TenderDocument.start_date < "' . $deadline . '" OR 
      TenderDocument.start_date <= "' . $deadline . '" AND 
      TenderDocument.required_date > "' . $deadline . '") AND 
      TenderDocument.id != ' . $id 
     ) 
    ) 
); 
$is_weekend = false; 
foreach($dates as $date) { 
    if(date('l',strtotime($date)) == 'Sunday' || date('l',strtotime($date)) == 'Saturday') { 
     $is_weekend = true; 
    } 
} 
while(!empty($is_available) || $is_weekend) { 
    $is_weekend = false; 
    $dates = array(); 
    $deadline = date('Y-m-d',strtotime('-1 day',strtotime($deadline))); 
    $start = date('Y-m-d',strtotime('-1 day',strtotime($start))); 
    $dates[] = $current = $start; 
    while($current < $deadline){ 
     $current = date('Y-m-d',strtotime('+1 day',strtotime($current))); 
     $dates[] = $current; 
    } 
    foreach($dates as $date) { 
     if(date('l',strtotime($date)) == 'Sunday' || date('l',strtotime($date)) == 'Saturday') { 
      $is_weekend = true; 
     } 
    } 
    $is_available = $this->TenderDocument->find('first', 
     array(
      'conditions' => array(
       '(TenderDocument.start_date >= "' . $start . '" AND 
       TenderDocument.start_date < "' . $deadline . '" OR 
       TenderDocument.start_date <= "' . $deadline . '" AND 
       TenderDocument.required_date > "' . $deadline . '") AND 
       TenderDocument.id != ' . $id 
      ) 
     ) 
    ); 
} 

На несвязанной ноте, есть ли способ я могу упростить/минимизировать этот код?

ответ

0

Я сделал это совершенно по-другому.

Я получил требуемую дату, создал диапазон дат от 2 месяцев, а затем удалил все субботы и воскресенья ПЛЮС, уже забронированные дни из массива. И затем я меняю сортировку и выбираю первое необходимое количество дней.

function _createDateRangeArray($strDateFrom,$strDateTo) { 
    $aryRange=array(); 

    $iDateFrom=mktime(1,0,0,substr($strDateFrom,5,2),  substr($strDateFrom,8,2),substr($strDateFrom,0,4)); 
    $iDateTo=mktime(1,0,0,substr($strDateTo,5,2),  substr($strDateTo,8,2),substr($strDateTo,0,4)); 

    if ($iDateTo>=$iDateFrom) 
    { 
     array_push($aryRange,date('Y-m-d',$iDateFrom)); // first entry 
     while ($iDateFrom<$iDateTo) 
     { 
      $iDateFrom+=86400; // add 24 hours 
      array_push($aryRange,date('Y-m-d',$iDateFrom)); 
     } 
    } 
    return $aryRange; 
} 

public function confirm($id = null) { 
    if($this->request->is('post')) { 
     $this->TenderDocument->create(); 
     $data = array(
      'TenderDocument' => array(
       'id' => $id, 
       'book_dates' => implode(',',$this->request->data['TenderDocument']['book_days']) 
      ) 
     ); 
     if($this->TenderDocument->save($data)) { 
      $this->_sendTenderDocument($id); 
      $this->Session->setFlash('Tender document request saved.','default',array('class'=>'notification')); 
      $this->redirect(array('action'=>'add')); 
     } else { 
      $this->Session->setFlash('There was an error saving your deadline. Please retry.','default',array('class'=>'error')); 
     } 
    } 
    $this->TenderDocument->id = $id; 
    if (!$this->TenderDocument->exists()) { 
     throw new NotFoundException(__('Invalid tender document')); 
    } 
    $tenderDocument = $this->TenderDocument->read(null,$id); 
    $deadline = $tenderDocument['TenderDocument']['required_date']; // Deadline date as entered on form 
    $deadline = $start = date('Y-m-d',strtotime('-1 day',strtotime($deadline))); // adjusted deadline 
    $start = date('Y-m-d',strtotime('-3 months',strtotime($deadline))); // adjusted start 
    $period = $this->_createDateRangeArray($start,$deadline); 
    $TenderDocuments = $this->TenderDocument->find('list', 
     array(
      'fields' => array('TenderDocument.book_dates') 
     ) 
    ); 
    $dates = array(); 
    foreach($TenderDocuments as $TenderDocument) { 
     $doc_dates = explode(',',$TenderDocument); 
     foreach($doc_dates as $doc_date) { 
      $dates[] = $doc_date; 
     } 
    } 
    foreach($period as $key=>$value) { 
     if(date('l',strtotime($value)) == 'Saturday' || date('l',strtotime($value)) == 'Sunday' || in_array($value,$dates)) { 
      unset($period[$key]); 
     } 
    } 
    rsort($period); 
    for($k = 0; $k <= $tenderDocument['ContractForm']['time']; $k++) { 
     $book_days[] = $period[$k]; 
    } 
    $this->set('TenderDocument',$this->TenderDocument->read(null,$id)); 
    $this->set('book_days',$book_days); 
} 

Если есть какой-либо способ, я могу рационализировать этот код и ускорить его, не стесняйтесь комментировать.

1

Надеюсь, я правильно понял вашу проблему, вам нужно рассчитать дату окончания контракта, учитывая количество дней, в течение которых он должен работать, без учета выходных дней в качестве рабочих дней.

Классы PHP DateTime могут значительно упростить ваш код. Я думаю, что эта функция поможет вам: -

/** 
* Given the start date of a contract will return the end date, skipping weekends 
* 
* @param String $starDate format 'Y-m-d' 
* @param Int $numberOfDays Number of working days 
* @return Array of date strings 
*/ 
function getDeadline($starDate, $numberOfDays) 
{ 
    $start = \DateTime::createFromFormat('Y-m-d', $starDate); 
    $interval = new DateInterval('P1D'); 
    $result = array(); 

    $i = 0; 
    while($i < $numberOfDays){ 
     if((int)$start->format('N') < 6){ 
      $result[] = $start->format('Y-m-d'); 
      $i++; 
     } 
     $start->add($interval); 
    } 
    return $result; 
} 

$start = '2013-6-12'; 
var_dump(getDeadline($start, 4)); 

Выход: -

array (size=4) 
    0 => string '2013-06-12' (length=10) 
    1 => string '2013-06-13' (length=10) 
    2 => string '2013-06-14' (length=10) 
    3 => string '2013-06-17' (length=10) 
+0

Вы находитесь на правильном пути, однако необходимо отметить эти даты, не отмечая выходных. Поэтому он должен в основном сделать чек, чтобы проверить, падает ли контракт на выходные, а затем отмечают (ради аргументов) пятница и понедельник на двухдневный контракт вместо пятницы и субботы. – Albert

+0

Я не уверен, что вы подразумеваете под «знаком». Вы ищете множество дней? Из уравнения уже выходят выходные. – vascowhite

+0

Массив дней будет работать. Я уверен, что этот кусок кода будет работать, поэтому я сделаю это. :) Спасибо – Albert

Смежные вопросы