我的截止日期为5天我需要为每个非工作日(周末或假日)添加+1天

问题描述 投票:0回答:1

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

我的餐桌假期

enter image description here

无论如何我已经尝试了但是我无法获得好结果

//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;
}
php mysql
1个回答
0
投票

使用DateTimeDateInterval,您可以在开始日期添加一些工作日,并提供可选的假期数组:

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"

由于您的假期存储在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);

给出输出:

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"
© www.soinside.com 2019 - 2024. All rights reserved.