PHP находит время, не затраченное на определенный промежуток времени между датами

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

Входы:

//This two is work start and end time.
$starttime="22:00";
$endtime="02:00";
//This two is person's entrance and exit time.
$entrance="2016-06-24 20:00:00"$exit="2016-06-25 05:00:00"

В этом случае ответ должен быть 5 часов. (Может быть в секундах)

Время входа и выхода может быть больше (несколько дней) или короче (тот же день). И время начала, и время окончания могут быть в один и тот же день. (например: 09: 00-10: 00)

Я проверил этот вопрос, но код работает неправильно, если период времени включает полночь.

Спасибо за ваши ответы.

1

Решение

Вот код для вас, код, который рассчитывает время и:

  • Не использует никаких циклов, которые очень неэффективны и не очень нужны.
  • Он рассчитывает время по минутам, чтобы иметь возможность точно обрабатывать любой час, например 14:27.
  • Код касается часов работы более полуночи.
  • Возвращает хороший массив с соответствующими данными, которые могут быть полезны для отладки.
  • результат указывается в [‘total_in_minutes’] в минутах, но также в [‘total_in_hours’] в часах.

    Выход:

        Array
    (
    [total_in_hours] => 5
    [total_in_minutes] => 300
    [days] => 1
    [is_over_midnight] => 1
    [total_min_first_day] => 120
    [total_min_middle_days] => 0
    [total_min_last_day] => 180
    )
    

    Код:

    $starttime="22:00";
    $endtime="02:00";
    $entrance="2016-06-24 20:00:00";
    $exit="2016-06-25 05:00:00";
    
    $time = calc_overtime($starttime, $endtime, $entrance, $exit);
    print_r($time);function calc_overtime($starttime, $endtime, $entrance, $exit){
    
    $total_days = date("d", strtotime($exit)) - date("d", strtotime($entrance));
    $working_hours[0] = array('start'=>get_minutes($starttime), 'end'=>get_minutes($endtime));
    $working_hours_a_day = ($working_hours[0]['end']-$working_hours[0]['start']);
    $over_midnight = (get_minutes($endtime)<get_minutes($starttime))?1:0;
    
    // split into two working hours which end>start in both
    if ($over_midnight) {
    $working_hours[0] = array('start'=>get_minutes($starttime), 'end'=> 24*60);
    $working_hours[1] = array('start'=>0, 'end'=>get_minutes($endtime));
    $working_hours_a_day = ($working_hours[0]['end']-$working_hours[0]['start'])+($working_hours[1]['end']-$working_hours[1]['start']);
    }
    
    // only one day - came and left the same day
    if ($total_days == 0){
    $total_overtime = calc_overtime_one_day(get_minutes($exit)-get_minutes($entrance), get_minutes($entrance), get_minutes($exit), $working_hours[0]['start'], $working_hours[0]['end']);
    $total_overtime = $over_midnight? calc_overtime_one_day($total_overtime, get_minutes($entrance), get_minutes($exit), $working_hours[1]['start'], $working_hours[1]['end']): $total_overtime;
    return array('total_in_hours'=>$total_overtime/60 ,'total_in_minutes'=>$total_overtime ,  'days' => $total_days, 'is_over_midnight'=>$over_midnight) ;
    }
    
    // More than one day
    $total_overtime_first_day = calc_overtime_one_day(24*60-get_minutes($entrance), get_minutes($entrance), 24*60, $working_hours[0]['start'], $working_hours[0]['end']);
    $total_overtime_first_day = $over_midnight ? calc_overtime_one_day($total_overtime_first_day, get_minutes($entrance), 24*60, $working_hours[1]['start'], $working_hours[1]['end']): $total_overtime_first_day;
    
    $total_overtime_last_day = calc_overtime_one_day(get_minutes($exit)-0, 0, get_minutes($exit), $working_hours[0]['start'], $working_hours[0]['end']);
    $total_overtime_last_day = $over_midnight ? calc_overtime_one_day($total_overtime_last_day, 0, get_minutes($exit), $working_hours[1]['start'], $working_hours[1]['end']):$total_overtime_last_day;
    
    $total_middle_days = ($total_days>1)? ((24*60-$working_hours_a_day)*($total_days-1)):0;
    $total = $total_overtime_first_day + $total_overtime_last_day + $total_middle_days;
    
    return array('total_in_hours'=>$total/60 , 'total_in_minutes'=>$total ,
    'days' => $total_days, 'is_over_midnight'=>$over_midnight, 'total_min_first_day'=>$total_overtime_first_day,
    'total_min_middle_days'=>$total_middle_days, 'total_min_last_day'=>$total_overtime_last_day) ;
    }function calc_overtime_one_day($current_minutes, $entrance, $exit, $gap_start, $gap_end){
    if ($entrance>=$gap_end || $exit <= $gap_start) { return $current_minutes; }
    
    $remove_end   = $gap_end;
    $remove_start = $gap_start;
    
    if ($entrance>=$gap_start) { $remove_start = $entrance; }
    if ($exit<=$gap_end) {$remove_end = $exit;}if ($exit<=$gap_end) {$remove_end = $exit;}
    
    return $current_minutes - ($remove_end-$remove_start);
    }function get_minutes($string_time){
    $timestamp = strtotime($string_time);
    return 60*date("H", $timestamp)+1*date("i", $timestamp);
    }
    
    0
  • Другие решения

    Если вы можете получить дату и время для starttime а также endtime маленькая функция getTimestampDiff будет делать то, что вам нужно.

    //This two is work start and end time.
    $starttime = "2016-06-24 22:00";
    $endtime   = "2016-06-25 02:00";
    //This two is person's entrance and exit time.
    $entrance = "2016-06-24 20:00:00";
    $exit     = "2016-06-25 05:00:00";
    
    function getTimestampDiff($startTime, $endTime)
    {
    $start = new DateTime($startTime);
    $end   = new DateTime($endTime);
    
    return $end->getTimestamp() - $start->getTimestamp();
    }
    
    $timeIdle    = getTimestampDiff($starttime, $endtime);
    $timeWorking = getTimestampDiff($entrance, $exit);
    
    $res = ($timeWorking - $timeIdle);
    
    echo sprintf("Time worked in minutes: %d<br />", $res / 60);
    echo sprintf("Time worked in hours: %d", $res / 60 / 60);
    

    Выход:

    Time worked in minutes: 300
    Time worked in hours: 5
    
    0

    По вопросам рекламы [email protected]