php - 计算 PHP 中不包括周末和时间段的时间差(以秒为单位)

标签 php mysql date datetime

我已经放弃尝试在 MySQL 中执行此操作,而是将结果注入(inject)到我的结果数组中(稍后在 JS 应用程序中使用)。

我有一个循环来遍历每个结果:

$data = $result->fetchAll();

foreach($data as $i => $row) {
    // Something                    
    $data[$i]['Age'] = $row['Age'];
}

我希望它将日期时间 $data[$i]['Age'] 与当前日期时间之间的秒数相加。

通常这很容易,但如何排除周末和 16:30 到 07:30 之间的时间?

最佳答案

我不认为这太具体或无趣,所以这是我的一位同事的答案:

public static function calculateTime($startDate, $endDate) {//Returns Seconds Passed

        date_default_timezone_set('Europe/London');

        //Opening Hours - Can pull from database depending on users working hours

        $workingHoursOpen = new DateTime('07:30:00');

        $workingHoursClose = new DateTime('16:30:00');



        //Time worked from and to

        $timeStarted = strtotime(date('H:i:s', strtotime($endDate)));

        $timeFinished = strtotime(date('H:i:s', strtotime($startDate)));



        $workingSeconds = $workingHoursClose->getTimestamp() - $workingHoursOpen->getTimestamp();

        $workingSecondsv2 = $timeFinished - $timeStarted;



        //Option to send array of holidays (3rd param)

        $workingDays = Util::getWorkingDays(date('Y-m-d', strtotime($startDate)), date('Y-m-d', strtotime($endDate)), array());



        $totalWorkingSeconds = $workingDays * $workingSeconds; //Working days * 9 hours



        $secondsClosed = 0;

        $i = 0;

        while ($i < $workingDays) {

            $secondsClosed = $secondsClosed - (15 * 3600);

            $i++;

        }



        $secondsPassed = ($workingSecondsv2 - $totalWorkingSeconds) + (9 * 3600);



        $secondsPassed = -1 * ($secondsPassed); // Invert number (was giving -XX)



        return $secondsPassed;

    }



    public static function getWorkingDays($startDate, $endDate, $holidays) {

        // do strtotime calculations just once

        $endDate = strtotime($endDate);

        $startDate = strtotime($startDate);



        $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);

            //If the holiday doesn't fall in weekend

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

                $workingDays--;

        }



        return $workingDays;

    }

100% 有效,并且可以扩展以从数据库引入工作时间。

关于php - 计算 PHP 中不包括周末和时间段的时间差(以秒为单位),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25364069/

相关文章:

MYSQL 服务器 ip 与 localhost 的工作方式不同

使用 JPA 标准 API 进行日期比较

javascript - 在 jQuery 中保持 GET 连接打开

php - 如何避免在双引号字符串中打印变量

c# - 找不到 ASP.NET Core 2 MySQL 8.0.8-dmr Entity Framework 扩展

mysql - MySQL 和 MariaDB 之间到底有什么区别?

php - 仅从数组中显示一次

php - 数据库中的复杂关系(使用 Laravel)

r - 日期转特定格式字符

java - 解析并检索日期时间的时区偏移量