2013-05-27 3 views
0

БрифинГ:Расчет рабочих дней с PHP: Это точно?

Я пытаюсь вычислим рабочих дней между двумя датами для системы управления пользовательского проекта, я в здании. Вот что я сделал до сих пор, как показано ниже. Кажется, он работает нормально, но я не уверен, насколько он точен и должен ли я использовать его или нет. Любая обратная связь будет высоко оценена!

КОД

<?php 

    # date variables: 
    date_default_timezone_set('Asia/Kuwait'); 
    $date['start'] = date('Y-m-d H:i:s'); 
    $date['end'] = '2013-12-01 08:00:00'; 
    $date['off'] = array('Friday','Saturday'); # usual days off in Kuwait) 

    # calculate the difference: 
    $date_s = new DateTime($date['start']); 
    $date_e = new DateTime($date['end']); 
    $interval = $date_s->diff($date_e); 

    # obtain relevant values: 
    $remaining_days = $interval->format('%r%a'); 
    $remaining_weeks = floor($remaining_days/7); 
    $weekend_days = ($remaining_weeks*count($date['off'])); 

    # additional holidays (just an example): 
    $extra_holidays_array = array 
    (
     'holiday 1' => '2013-06-24 00:00:00', 
     'holiday 2' => '2013-06-25 00:00:00', 
     'holiday 3' => '2013-07-01 00:00:00', 
     'holiday 4' => '2013-08-24 00:00:00' 
    ); 

    # check if a real holiday: 
    $extra_holidays = 0; 
    foreach($extra_holidays_array as $check_date) 
    { 
     $day_of_holiday = date('l', strtotime($check_date)); 
     if(! in_array($day_of_holiday,$date['off'])){ $extra_holidays++; } 
    } 

    # total holidays: 
    $total_holidays = ($weekend_days+$extra_holidays); 

    # business days: 
    $business_days_nh = ($remaining_days-$weekend_days); # NO extra holidays 
    $business_days_wh = ($remaining_days-$weekend_days-$extra_holidays); # WITH extra holidays 

?> 

<ul> 
<li>Current Date: <?php echo $date['start']; ?></li> 
<li>Deadline Date: <?php echo $date['end']; ?></li> 
</ul> 
<ul> 
<li>Remaining Days: <?php echo $remaining_days; ?></li> 
<li>Remaining Weeks: <?php echo $remaining_weeks; ?></li> 
</ul> 
<ul> 
<li>Usual Holidays: <?php echo $weekend_days; ?></li> 
<li>Extra Holidays: <?php echo $extra_holidays; ?></li> 
<li>Total Holidays: <?php echo $total_holidays; ?></li> 
</ul> 
<ul> 
<li>Business Days (Before Holidays): <?php echo $business_days_nh; ?></li> 
<li>Business Days (After Holidays): <?php echo $business_days_wh; ?></li> 
</ul> 
+1

У вас есть комплект модульных тестов, охватывающих крайние случаи? –

+1

Извините, я не понимаю. Что ты конкретно имеешь ввиду? Если то, что я предполагаю, правильно, то если дата начала равна или больше даты окончания, я получаю отрицательные значения, которые не являются проблемой для меня. –

+0

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

ответ

1

Я написал функцию в предыдущем проекте для этой точной цели:

Вот что использовать в качестве параметров:

  • $ запуска - Start Unix timestamp (вы можете использовать strtotime ('1 января 2013 года), чтобы получить отметку времени
  • $ end - E й Отметка времени Unix
  • факультативных $ праздников - массив дат сосчитать, как праздники (IE праздничные и т.д.), он использует strtotime() для преобразования даты
  • Дополнительно $ returnAsArray - Возвращает список рабочих дней метки времени, или просто номер рабочих дней

Важные Его важно знать, временные метки данный должны быть отметки времени для начала дня, например:

для использования 1-го января 2013 года в качестве метки времени, используйте значение пользователя: mktime(0, 0, 0, 1, 1, 2013);

function networkDays($start, $end, array $holidays = array(), $returnAsArray = false) 
{ 
    if(!is_int($start)){ 
     trigger_error('Parameter 1 expected to be integer timestamp. ' . ucfirst(gettype($start)) . ' given.', E_USER_WARNING); 
     return false; 
    } 

    if(!is_int($end)){ 
     trigger_error('Parameter 2 expected to be integer timestamp. ' . ucfirst(gettype($start)) . ' given.', E_USER_WARNING); 
     return false; 
    } 

    if(!is_array($holidays)){ 
     $holidays = array(); 
     trigger_error('Parameter 3 expected to be Array. ' . ucfirst(gettype($holidays)) . ' given.', E_USER_NOTICE); 
    } 

    if(!is_bool($returnAsArray)){ 
     trigger_error('Parameter 4 expected to be Boolean. ' . ucfirt(gettype($returnAsArray)) . ' given.', E_USER_WARNING); 
     return false; 
    } 


    if($start>=$end){ 
     $nEnd = $start; 
     $nStart = $end; 

     $start = $nStart; 
     $end = $nEnd; 
    } 


    foreach($holidays as $key => $holiday) 
    { 
     $holidays[$key] = strtotime($holiday); 
    } 


    $numberOfDays = ceil(((($end-$start)/60)/60)/24); 

    $networkDay = 0; 
    $networkDayArray = array(); 

    for($d = 0; $d < $numberOfDays; $d++) 
    { 
     $dayTimestamp = $start+(86400*$d); 

     if(date('N',$dayTimestamp)<6 && !in_array($dayTimestamp,$holidays)) 
     { 
      $networkDay += 1; 
      $networkDayArray[] = $dayTimestamp; 
     } 
    } 


    if($returnAsArray) 
    { 
     return $networkDayArray; 
    } else { 
     return $networkDay; 
    } 
} 
Смежные вопросы