doujiao4705 2012-01-18 17:16
浏览 204

计算两个日期之间的工作时间

I need a PHP method for calculating working hours between two dates based on a 8 hour working day and excluding weekends and bank holidays.

For example the difference between 2012-01-01T08:30:00 AND 2012-01-05T10:30:00 in working hours is actually 26 working hours because the first two days are weekend/bank holiday which just leaves 3 working days and the time differnce of 2 hours i.e. 3*8+2=26.

I have used @flamingLogos excellent answer to a previous question but cannot get it to take into account the time as well as date.

  • 写回答

3条回答 默认 最新

  • dongsimang4036 2012-01-19 14:02
    关注

    Maybe you can use this function :

    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.5, 17.5); // 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("
    From %s To %s : %d hours
    ",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("
    From %s To %s : %d working days
    ",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("
    From %s To %s : %d hours
    ",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("
    From %s To %s : %d hours
    ",date('d/m/y H:i',$date1),date('d/m/y H:i',$date2),$seconds/3600);
    
        return $sign * $seconds/3600; // to get hours
    }
    

    I put printf() to show what it is done (you can remove them)

    You call it like that :

    date_default_timezone_set("America/Los_Angeles");
    $dt2 = strtotime("2012-01-01 05:25:00");
    $dt1 = strtotime("2012-01-19 12:40:00");
    echo work_hours_diff($dt1 , $dt2 );
    
    评论

报告相同问题?

悬赏问题

  • ¥30 深度学习,前后端连接
  • ¥15 孟德尔随机化结果不一致
  • ¥15 apm2.8飞控罗盘bad health,加速度计校准失败
  • ¥15 求解O-S方程的特征值问题给出边界层布拉休斯平行流的中性曲线
  • ¥15 谁有desed数据集呀
  • ¥20 手写数字识别运行c仿真时,程序报错错误代码sim211-100
  • ¥15 关于#hadoop#的问题
  • ¥15 (标签-Python|关键词-socket)
  • ¥15 keil里为什么main.c定义的函数在it.c调用不了
  • ¥50 切换TabTip键盘的输入法