自定义工作日的两个日期之间的总工作日

时间:2015-08-09 07:07:10

标签: php mysql

我想通过使用自定义关闭日来计算两个日期之间的总工作日。我插入星期一,星期六和星期天是休息日。但是,当我从开始日期2015-07-26和结束日期2015-08-26计算时,结果是正确的。但是,如果开始日期为2015-08-01,结束日期为2015-08-31,则结果不正确。

我该怎么做?

这是我的代码

<?php 
include 'connect.php';
error_reporting(E_ALL ^ E_NOTICE);
if (isset($_POST['startdate']) && isset($_POST['enddate']))
{
        $startdate=$_POST['startdate'];
        $enddate=$_POST['enddate'];
        $no = 0;

    $daysdiff = floor(((strtotime($enddate) -strtotime($startdate)) / 86400)+1); 
        echo "total day is".$daysdiff;

    $startdate = new DateTime($startdate);
    $enddate= new DateTime($enddate);
    $interval = DateInterval::createFromDateString('1 day');
    $period = new DatePeriod($startdate, $interval, $enddate);

    $res=mysql_query("SELECT * From working_day") or die(mysql_error());
    while ($row = mysql_fetch_assoc($res))
    {
        $id=$row['id'];
        $name_value=$row['off_days'];


        foreach ($period as $dt)
        {
            if (($dt->format('N')== $id ))
            {
            $no++;
            //$result=$daysdiff-$no;
            }
        }
        $result=$daysdiff-$no;                      

    }
    echo "<input class='form-control' type='text' name='working_day' value='$result'  />";

}
?>

1 个答案:

答案 0 :(得分:1)

我使用了一个功能,我相信很久以前我从这个网站上获得了这个功能来计算我的网络应用中员工的休假时间。这是完整的功能,我还从一个名为“holiday_dates”的表中考虑自定义假期:

function countWorkingDays($startDate,$endDate)
{
    $pdoCore = Core::getInstance();

    // Build the holiday array
    $holidays_q = $pdoCore->dbh->prepare("SELECT holidayDate FROM holiday_dates");
    $holidays_q->execute();

    while($holidays_a = $holidays_q->fetch(PDO::FETCH_ASSOC))
    {
        $holidays[] = $holidays_a['holidayDate'];
    }

    // 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 and 6 <= $the_last_day_of_week)
        {
            $no_remaining_days--;
        }
        if($the_first_day_of_week <= 7 and 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);

        //If the holiday doesn't fall in weekend
        if($startDate <= $time_stamp and $time_stamp <= $endDate and date("N",$time_stamp) != 6 and date("N",$time_stamp) != 7)
        {
            $workingDays--;
        }
    }

    return $workingDays;
}

对于您的用例,我要说注意这一行:

if($startDate <= $time_stamp and $time_stamp <= $endDate and date("N",$time_stamp) != 6 and date("N",$time_stamp) != 7)

并在周一添加:

 and date("N",$time_stamp) != 1