2016-01-05 2 views
0

Я бы хотел (а) рассчитать рабочее время между двумя датами. Я использую функцию work_hours_diff, на которую здесь дан ответ; https://stackoverflow.com/a/8927347/4671728PHP - Расчет рабочего времени между двумя датами

На самом деле, это вычисление нормальны, но когда я ввод два же дата, но различные часы, он возвращает неправильные значения. Например; 29-12-2015 13:17:43 и 29-12-2015 11:17:39 - Он возвращает 11 часов, но он должен быть возвращен 2 часа. Однако, когда я вводил разные даты от eachother, он вычисляет правильно.

Вы можете найти коды ниже;

function work_hours_diff($date1,$date2) { 
if ($date1>$date2) { $tmp=$date1; $date1=$date2; $date2=$tmp; unset($tmp); $sign=-1; } else $sign = 1; 
if ($date1==$date2) return 0; 

$days = 0; 
$working_days = array(1,2,3,4,5); // Monday-->Friday 
$working_hours = array(8, 17); // from 8:30(am) to 17:30 
$current_date = $date1; 
$beg_h = floor($working_hours[0]); $beg_m = ($working_hours[0]*60)%60; 
$end_h = floor($working_hours[1]); $end_m = ($working_hours[1]*60)%60; 

// setup the very next first working timestamp 

if (!in_array(date('w',$current_date) , $working_days)) { 
    // the current day is not a working day 

    // the current timestamp is set at the begining of the working day 
    $current_date = mktime($beg_h, $beg_m, 0, date('n',$current_date), date('j',$current_date), date('Y',$current_date)); 
    // search for the next working day 
    while (!in_array(date('w',$current_date) , $working_days)) { 
     $current_date += 24*3600; // next day 
    } 
} else { 
    // check if the current timestamp is inside working hours 

    $date0 = mktime($beg_h, $beg_m, 0, date('n',$current_date), date('j',$current_date), date('Y',$current_date)); 
    // it's before working hours, let's update it 
    if ($current_date<$date0) $current_date = $date0; 

    $date3 = mktime($end_h, $end_m, 59, date('n',$current_date), date('j',$current_date), date('Y',$current_date)); 
    if ($date3<$current_date) { 
     // outch ! it's after working hours, let's find the next working day 
     $current_date += 24*3600; // the day after 
     // and set timestamp as the begining of the working day 
     $current_date = mktime($beg_h, $beg_m, 0, date('n',$current_date), date('j',$current_date), date('Y',$current_date)); 
     while (!in_array(date('w',$current_date) , $working_days)) { 
      $current_date += 24*3600; // next day 
     } 
    } 
} 

// so, $current_date is now the first working timestamp available... 

// calculate the number of seconds from current timestamp to the end of the working day 
$date0 = mktime($end_h, $end_m, 59, date('n',$current_date), date('j',$current_date), date('Y',$current_date)); 
$seconds = $date0-$current_date+1; 

//printf("<br>From %s To %s : %d hours<br>",date('d/m/y H:i',$date1),date('d/m/y H:i',$date0),$seconds/3600); 

// calculate the number of days from the current day to the end day 

$date3 = mktime($beg_h, $beg_m, 0, date('n',$date2), date('j',$date2), date('Y',$date2)); 
while ($current_date < $date3) { 
    $current_date += 24*3600; // next day 
    if (in_array(date('w',$current_date) , $working_days)) $days++; // it's a working day 
} 
if ($days>0) $days--; //because we've allready count the first day (in $seconds) 

//printf("<br>From %s To %s : %d working days<br>",date('d/m/y H:i',$date1),date('d/m/y H:i',$date3),$days); 

// check if end's timestamp is inside working hours 
$date0 = mktime($beg_h, 0, 0, date('n',$date2), date('j',$date2), date('Y',$date2)); 
if ($date2<$date0) { 
    // it's before, so nothing more ! 
} else { 
    // is it after ? 
    $date3 = mktime($end_h, $end_m, 59, date('n',$date2), date('j',$date2), date('Y',$date2)); 
    if ($date2>$date3) $date2=$date3; 
    // calculate the number of seconds from current timestamp to the final timestamp 
    $tmp = $date2-$date0+1; 
    $seconds += $tmp; 
    //printf("<br>From %s To %s : %d hours<br>",date('d/m/y H:i',$date2),date('d/m/y H:i',$date3),$tmp/3600); 
} 

// calculate the working days in seconds 

$seconds += 3600*($working_hours[1]-$working_hours[0])*$days; 

//printf("<br>From %s To %s : %d hours<br>",date('d/m/y H:i',$date1),date('d/m/y H:i',$date2),$seconds/3600); 

//return $sign * $seconds/3600; // to get hours 
return round($seconds/3600); 
} 

date_default_timezone_set("Europe/Istanbul"); 
$dt2 = strtotime("29-12-2015 11:17:39"); 
$dt1 = strtotime("29-12-2015 13:17:43"); 
echo work_hours_diff($dt1 , $dt2); 
+0

вопрос о ответе от другого вопроса, давайте быть осторожными мы не создаем черную дыру. –

ответ

0

Замените эту строку:

if ($days>0) $days--; //because we've allready count the first day (in $seconds) 

с:

$days--; //because we've allready count the first day (in $seconds) 

Это if было плохо, так как это удалило различие между $ дней значения 0 и 1 (перед if), которые просто не могут быть правы.

+0

Спасибо, это работает :) –

0

Попробуйте это ..

date_default_timezone_set("Europe/Istanbul"); 
$dt2 = strtotime("29-12-2015 11:17:39"); 
$dt1 = strtotime("29-12-2015 13:17:43"); 
echo $diff_hours = ($dt1 - $dt2)/3600; 

Выход

2.0011111111111 hours 
+0

Спасибо за ваш ответ, но я должен рассчитать без выходных и просто включить часы работы между датами. Ваши коды просто вычисляют все часы между датами. Функция work_hours_diff работает для меня, но когда я вхожу в ту же дату с разными часами, она не вычисляется правильно. Однако, если я вхожу в разные даты, он вычисляет правильно. Я просто хочу решить эту проблему. –

0

Заменить

if ($days>0) $days--; //because we've allready count the first day (in $seconds) 

Для этого:

if (in_array(date('w',$date2) , $working_days)) { 
    $days--; //because we've allready count the first day (in $seconds) 
} 
Смежные вопросы