Php 我有一个最后期限是5天,我需要添加+;每非工作日(周末或节假日)1天

Php 我有一个最后期限是5天,我需要添加+;每非工作日(周末或节假日)1天,php,mysql,Php,Mysql,我试图制定一个规则,我的最后期限是5天,我需要为每个非工作日(周末或假日)加上+1天。还有下表的节假日提醒,如果最后一天不能是周末或节假日 我的桌子假日 我已经试过了,但没有好结果 //The function returns the no. of business days between two dates and it skips the holidays function getWorkingDays($startDate,$endDate,$holidays){ // do

我试图制定一个规则,我的最后期限是5天,我需要为每个非工作日(周末或假日)加上+1天。还有下表的节假日提醒,如果最后一天不能是周末或节假日

我的桌子假日

我已经试过了,但没有好结果

//The function returns the no. of business days between two dates and it skips the holidays
function getWorkingDays($startDate,$endDate,$holidays){
    // do strtotime calculations just once
    $endDate = strtotime($endDate);
    $startDate = strtotime($startDate);


    //The total number of days between the two dates. We compute the no. of seconds and divide it to 60*60*24
    //We add one to inlude both dates in the interval.
    $days = ($endDate - $startDate) / 86400 + 1;

    $no_full_weeks = floor($days / 7);
    $no_remaining_days = fmod($days, 7);

    //It will return 1 if it's Monday,.. ,7 for Sunday
    $the_first_day_of_week = date("N", $startDate);
    $the_last_day_of_week = date("N", $endDate);

    //---->The two can be equal in leap years when february has 29 days, the equal sign is added here
    //In the first case the whole interval is within a week, in the second case the interval falls in two weeks.
    if ($the_first_day_of_week <= $the_last_day_of_week) {
        if ($the_first_day_of_week <= 6 && 6 <= $the_last_day_of_week) $no_remaining_days--;
        if ($the_first_day_of_week <= 7 && 7 <= $the_last_day_of_week) $no_remaining_days--;
    }
    else {
        // (edit by Tokes to fix an edge case where the start day was a Sunday
        // and the end day was NOT a Saturday)

        // the day of the week for start is later than the day of the week for end
        if ($the_first_day_of_week == 7) {
            // if the start date is a Sunday, then we definitely subtract 1 day
            $no_remaining_days++;

            if ($the_last_day_of_week == 6) {
                // if the end date is a Saturday, then we subtract another day
                $no_remaining_days++;
            }
        }
        else {
            // the start date was a Saturday (or earlier), and the end date was (Mon..Fri)
            // so we skip an entire weekend and subtract 2 days
            $no_remaining_days += 2;
        }
    }

    //The no. of business days is: (number of weeks between the two dates) * (5 working days) + the remainder
    //---->february in none leap years gave a remainder of 0 but still calculated weekends between first and last day, this is one way to fix it
   $workingDays = $no_full_weeks * 5;
    if ($no_remaining_days > 0 )
    {
      $workingDays += $no_remaining_days;
    }

    //We subtract the holidays
    foreach($holidays as $holiday){
        $time_stamp=strtotime($holiday->data);
        //If the holiday doesn't fall in weekend
        if ($startDate <= $time_stamp && date("N",$time_stamp) != 6 && date("N",$time_stamp) != 7)
            $workingDays++;
    }

    return $workingDays;
}
//函数返回两个日期之间的工作日数,并跳过假期
函数getWorkingDays($startDate、$endDate、$holidays){
//只进行一次strotime计算
$endDate=strottime($endDate);
$startDate=strottime($startDate);
//两个日期之间的总天数。我们计算秒数并将其除以60*60*24
//我们在间隔中的两个日期中都添加一个。
$days=($endDate-$startDate)/86400+1;
$no_full_weeks=最低限额($days/7);
$no_剩余天数=fmod($d,7);
//如果是星期一,它将返回1,如果是星期天,它将返回7
$每周的第一天=日期(“N”,开始日期);
$U周的最后一天=日期(“N”,$endDate);
//---->二者在闰年中可以相等,二月有29天,这里加上等号
//在第一种情况下,整个间隔在一周内,在第二种情况下,间隔在两周内。

如果使用
DateTime
DateInterval
将($作为一周的第一天),您可以向开始日期添加若干个工作日,并可选择假日数组:

function getDeadline($start_date, $working_days, array $holiday_dates = array())
{
    $date = DateTime::createFromFormat('Y-m-d', $start_date);
    $interval = new DateInterval('P1D'); // one day
    $holiday_dates = array_flip($holiday_dates); // so we can use isset to check for holidays
    while (
        $date->format('N') >= 6 // weekend day
        || isset($holiday_dates[$date->format('Y-m-d')]) // OR holiday
        || $working_days-- > 0 // OR deadline working days left to add
    ) {
        $date->add($interval); // move to next day
    }
    return $date->format('Y-m-d');
}
测试如下:

var_dump(getDeadline('2017-12-21', 5)); // only weekends
var_dump(getDeadline('2017-12-21', 5, array('2017-12-22', '2017-12-26'))); // weekends and holidays
给出输出:

string(10) "2017-12-28"
string(10) "2018-01-01"
array(6) {
  [0]=>
  string(10) "2017-12-22"
  [1]=>
  string(10) "2017-12-26"
  [2]=>
  string(10) "2017-12-27"
  [3]=>
  string(10) "2018-01-01"
  [4]=>
  string(10) "2018-01-02"
  [5]=>
  string(10) "2018-01-03"
}
string(10) "2018-01-05"
由于您的假期存储在mysql中,您可以使用如下函数在单个查询中提取假期:

function getHolidays($start_date)
{
    $database = new PDO(/* your connection details here */);
    $statement = $database->prepare("
        SELECT DISTINCT date
        FROM holiday
        WHERE date >= :start_date
        ORDER BY date ASC;
    ");
    $statement->bindValue(':start_date', $start_date);
    $statement->execute();
    return $statement->fetchAll(PDO::FETCH_COLUMN);
}
假设
holidays
表如您的问题所示存在,您可以组合这些函数来获取截止日期:

$holidays = getHolidays('2017-12-21');
var_dump($holidays);
$deadline_end_date = getDeadline('2017-12-21', 5, $holidays);
var_dump($deadline_end_date);
给出输出:

string(10) "2017-12-28"
string(10) "2018-01-01"
array(6) {
  [0]=>
  string(10) "2017-12-22"
  [1]=>
  string(10) "2017-12-26"
  [2]=>
  string(10) "2017-12-27"
  [3]=>
  string(10) "2018-01-01"
  [4]=>
  string(10) "2018-01-02"
  [5]=>
  string(10) "2018-01-03"
}
string(10) "2018-01-05"

您的应用程序中有数据库吗?您好,欢迎使用Stack Overflow!在您的示例中,您提供了大量代码。请尝试将其简化为一个。您的问题越简化,我们就越容易帮助您,尽管目前情况下,您已经为我们提供了大量代码,让我们进行筛选,以了解发生了什么。同样,请请解释您所说的“未能获得良好结果”是什么意思。您是否收到错误消息?输出错误?请与我们分享您收到的输出,这将使错误更容易找到。strotime(日期(“Y-m-d”,strotime($startDate+”)(1+getWorkingDays($startDate,$endDate,$holidays))。“天”))回归2018-01-02这是一个完美的假期!你是最棒的,我试了好几天!完美,完美!