2013-11-29 3 views
-4

Может ли кто-нибудь помочь мне написать функцию, которая вычисляет количество рабочих часов между двумя датами, но хочет исключить время, когда запрос имел статус «В ожидании».PHP - Расчет рабочего времени между двумя датами, но исключение времени, когда запрос приостановлен

Так что скажем, что запрос пришел в пятницу в 3 часа ночи и был закрыт в 3 часа дня в среду, а рабочее время - с 8 утра до 5 вечера Тихого океана (с понедельника по пятницу) ... Всего рабочих часов будет 27 часов ... но если запрос оставался в ожидании с понедельника 3 вечера до вторника 3 вечера ... Фактическое рабочее время по запросу действительно составляет 18 часов вместо 27 часов.

Я недавно начал работать над PHP и мне была поручена эта задача, которая мне очень сбивает с толку. Пожалуйста, помогите

+2

Я думаю, что важно сказать, как хранятся ваши данные. –

ответ

0

Рассчитать время работы с точностью до 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; 
} 
+0

Спасибо, что нашли время, чтобы ответить на этот вопрос. Я думаю, что ** Asenar ** ответ очень близок к тому, что я искал – Tahir

+0

Эта функция на самом деле очень проста и крута. однако он возвращает три дополнительных часа каждый раз, когда я запускаю это. Вышеприведенный пример должен возвращать 15, тогда как он возвращает 18. – Tahir

+0

Я исправил функцию, чтобы вернуть мне правильные значения. В основном у вас была просто отсутствующая «=» с большим и меньшим количеством знаков. Теперь осталось единственное, что сводит меня с ума, это логика расчета минут. Не могли бы вы посоветовать мне, как это сделать, используя вашу функцию? – Tahir

1

Все, что вам нужно сделать, это получить общее истекшее время, затем вычитать в нерабочее время.

Вы можете использовать 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); 
+0

Спасибо за помощь. Таким образом, в основном я буду называть эту функцию дважды, чтобы получить общее рабочее время, а затем общее количество часов на удержании (после дачи начала и окончания даты/времени для удержания) ... Минус от общего рабочего времени, и это должно дать мне фактическое время запроса, правильно ли? – Tahir

+0

Извините, что я не уверен, что вы понимаете под «удержанием», но этот код прост: для каждого дня он добавляет отработанные часы, за исключением случаев, когда это первый или последний день. Если вы хотите рассчитать другое время, вы можете изменить этот код, чтобы добавить другие переменные внутри правильной части if/else, я не уверен, что вызов его дважды может что-то сделать. Но, конечно, вы можете попробовать, и если это не сработает для вас, добавьте некоторые строки отладки, такие как «эхо» до сих пор, формат «. $ Date-> (« Ym-d »).», Work_time = $ work_time
";' чтобы посмотреть, как рассчитывается время. – Asenar

+0

Базовый уровень удержания - это время, в течение которого запрос не работал, поскольку для этого требовалось больше информации. Поэтому мне нужно минус время ожидания от общего времени. так что предположим, что если время начала и окончания запроса составляет 20 часов, а промежуток времени между тем, где этот запрос был приостановлен, было 10-часовое время ... общее время станет общим временем = общее время (от начала до конца) минус время удержания. – Tahir

Смежные вопросы