我试图制定规则,我的截止日期是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;
}
答案 0 :(得分:0)
使用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"
由于您的假期存储在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"