簡體   English   中英

用PHP計算以秒為單位的時差(不包括周末和時間段)

[英]Calculate time difference in seconds excluding weekends and a time period in PHP

我已經放棄嘗試在MySQL中執行此操作,而是將結果注入到我的結果數組中(稍后在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%工作,並且可以擴展以從數據庫中引入工作時間。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM