1

我有一个 CakePHP 应用程序,它被用作我们公司日常活动的中心门户。这些包括各种预订系统和信息,例如员工及其部门。系统运行 CakePHP 2.2

我目前正在实施的是一个系统,一个进行招标的人可以申请起草合同。该合同有各种变化,这取决于合同草案应在(投标的)截止日期前多长时间移交给法人,以起草正式合同。然后系统“预订”该合同成立的几天内的法人。那些日子不能进行其他预订。

该系统运行良好,但不会在周末拆分合同。它整天移动到周末之前。假设为了争论,我预定了一份合同草案,以在 6 月 18 日完成。系统确定总合同时间为 3 天。这意味着合同应该在一个周末结束,并且应该在 6 月 13 日、14 日和 17 日(不是 18 日,因为那时我需要完成文件)。但是,系统会在 6 月 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
            )
        )
    );
}

在不相关的说明中,有什么方法可以简化/最小化此代码?

4

2 回答 2

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)
于 2013-06-12T12:05:05.157 回答
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);
}

如果有任何方法可以简化此代码并使其更快,请随时发表评论。

于 2013-08-21T06:55:30.293 回答