PHP-计算两个日期之间的工作时间,但不包括请求被搁置的时间


PHP - Calculating working hours between two dates but exclude the time when request is on hold

有人能帮我写一个函数来计算两个日期之间的工作小时数,但要排除请求状态为"挂起"的时间吗。

比方说,请求是在周五下午3点收到的,周三下午3点关闭,工作时间是太平洋地区(周一至周五)上午8点至下午5点。。。总工作时间为27小时。。。但如果请求从周一下午3点一直搁置到周二下午3点。。。请求的实际工作时间实际上变成了18小时,而不是27小时。

我最近开始研究PHP,并被分配了这个任务,这让我很困惑。请帮助

您所要做的就是获取所用的总时间,然后减去非工作时间。

您可以使用dateTime和datePeriod php对象(需要php 5.3)

这里有一个小脚本来做你想做的事(但你可能需要适应你的需求)

<?php
ini_set('display_errors', 'on');
define('DAY_WORK', 32400); // 9 * 60 * 60
define('HOUR_START_DAY', '08:00:00');
define('HOUR_END_DAY', '17:00:00');
// get begin and end dates of the full period
$date_begin = '2013-11-29 15:00:00';
$date_end = '2013-12-03 15:00:00';
// keep the initial dates for later use
$d1 = new DateTime($date_begin);
$d2 = new DateTime($date_end);
// and get the datePeriod from the 1st to the last day
$period_start = new DateTime($d1->format('Y-m-d 00:00:00'));
$period_end   = new DateTime($d2->format('Y-m-d 23:59:59'));
$interval = new DateInterval('P1D');
//$interval = new DateInterval('weekdays'); // 1 day interval to get all days between the period
$period = new DatePeriod($period_start, $interval, $period_end);
$worked_time = 0;
$nb = 0;
// for every worked day, add the hours you want
foreach($period as $date){
  $week_day = $date->format('w'); // 0 (for Sunday) through 6 (for Saturday)
  if (!in_array($week_day,array(0, 6)))
  {
    // if this is the first day or the last dy, you have to count only the worked hours 
    if ($date->format('Y-m-d') == $d1->format('Y-m-d'))
    {
        $end_of_day_format = $date->format('Y-m-d '.HOUR_END_DAY);
        $d1_format = $d1->format('Y-m-d H:i:s');
        $end_of_day = new DateTime($end_of_day_format);
        $diff = $end_of_day->diff($d1)->format("%H:%I:%S");
        $diff = split(':', $diff);
        $diff = $diff[0]*3600 + $diff[1]*60 + $diff[0];
        $worked_time += $diff;
    }
    else if ($date->format('Y-m-d') == $d2->format('Y-m-d'))
    {
        $start_of_day = new DateTime($date->format('Y-m-d '.HOUR_START_DAY));
        $d2_format = $d2->format('Y-m-d H:i:s');
        $end_of_day = new DateTime($end_of_day_format);
        $diff = $start_of_day->diff($d2)->format('%H:%I:%S');
        $diff = split(':', $diff);
        $diff = $diff[0]*3600 + $diff[1]*60 + $diff[0];
        $worked_time += $diff;
    }
    else
    {
        // otherwise, just count the full day of work
        $worked_time += DAY_WORK;
    }
  }
  if ($nb> 10)
    die("die ".$nb);
}
echo sprintf('Works from %s to %s, You worked %d hour(s)', $date_begin, $date_end, $worked_time/60/60);

计算工作时间,精确到1分钟。

警告:此函数可能需要几秒钟才能加载,因为它在时间跨度之间每分钟都会循环一次

<?php
$request = array(
    'start' => '3PM Nov 29 2013',
    'end' => '3PM Dec 4 2013'
);
echo calculate_work($request);
/**
 * Calculate work time by looping through every minute
 * @param  array $request start to end time
 * @return int  work time in minutes
 */
function calculate_work($request)
{
    $start = strtotime($request['start']);
    $end = strtotime($request['end']);
    $work_time = 0;
    /* Add 1 minute to the start so that we don't count 0 as a minute  */
    for ($time = $start + 60; $time <= $end; $time += 60)
    {
        // Weekends
        if (date('D', $time) == 'Sat' OR date('D', $time) == 'Sun')
            continue;
        // Non Working Hours
        if (date('Hi', $time) <= '0800' OR date('Hi', $time) > '1700')
            continue;
        // On Hold
        if ($time > strtotime('3PM Dec 2 2013') AND $time <= strtotime('3PM Dec 3 2013'))
            continue;
        $work_time++;
    }
    // Divide by 60 to turn minutes into hours
    return $work_time / 60;
}
/**
 * Get the total working hours in seconds between 2 dates..
 * @param DateTime $start Start Date and Time
 * @param DateTime $end Finish Date and Time
 * @param array $working_hours office hours for each weekday (0 Monday, 6 Sunday), Each day must be an array containing a start/finish time in seconds since midnight.
 * @return integer
 * @link https://github.com/RCrowt/working-hours-calculator
 */
function getWorkingHoursInSeconds(DateTime $start, DateTime $end, array $working_hours)
{
    $seconds = 0; // Total working seconds
    // Calculate the Start Date (Midnight) and Time (Seconds into day) as Integers.
    $start_date = clone $start;
    $start_date = $start_date->setTime(0, 0, 0)->getTimestamp();
    $start_time = $start->getTimestamp() - $start_date;
    // Calculate the Finish Date (Midnight) and Time (Seconds into day) as Integers.
    $end_date = clone $end;
    $end_date = $end_date->setTime(0, 0, 0)->getTimestamp();
    $end_time = $end->getTimestamp() - $end_date;
    // For each Day
    for ($today = $start_date; $today <= $end_date; $today += 86400) {
        // Get the current Weekday.
        $today_weekday = date('w', $today);
        // Skip to next day if no hours set for weekday.
        if (!isset($working_hours[$today_weekday][0]) || !isset($working_hours[$today_weekday][1])) continue;
        // Set the office hours start/finish.
        $today_start = $working_hours[$today_weekday][0];
        $today_end = $working_hours[$today_weekday][1];
        // Adjust Start/Finish times on Start/Finish Day.
        if ($today === $start_date) $today_start = min($today_end, max($today_start, $start_time));
        if ($today === $end_date) $today_end = max($today_start, min($today_end, $end_time));
        // Add to total seconds.
        $seconds += $today_end - $today_start;
    }
    return gmdate("H:i:s", $seconds);
}