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

PHP-计算两个日期之间的工作时间,php,date,time,Php,Date,Time,我想计算两个日期之间的工作时间。我使用的是这里回答的工作时间差函数 实际上,它是正常计算的,但当我输入两个相同的日期但不同的小时数时,它返回错误的值。例如2015年12月29日13:17:43和2015年12月29日11:17:39-它返回11小时,但应该返回2小时。但是,当我输入彼此的不同日期时,它计算正确 您可以找到下面的代码 function work_hours_diff($date1,$date2) { if ($date1>$date2) { $tmp=$date1; $dat

我想计算两个日期之间的工作时间。我使用的是这里回答的工作时间差函数

实际上,它是正常计算的,但当我输入两个相同的日期但不同的小时数时,它返回错误的值。例如2015年12月29日13:17:43和2015年12月29日11:17:39-它返回11小时,但应该返回2小时。但是,当我输入彼此的不同日期时,它计算正确

您可以找到下面的代码

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 );
function work\u hours\u diff($date1,$date2){
如果($date1>$date2){$tmp=$date1;$date1=$date2;$date2=$tmp;unset($tmp);$sign=-1;}否则$sign=1;
如果($date1==$date2)返回0;
$days=0;
$working_days=数组(1,2,3,4,5);//星期一-->星期五
$working_hours=array(8,17);//从上午8:30到17:30
$current_date=$date1;
$beg_h=楼层($working_u u h[0]);$beg_m=($working_u u h[0]*60)%60;
$end_h=楼层($working_h[1]);$end_m=($working_h[1]*60)%60;
//设置下一个第一个工作时间戳
if(!in_数组(日期('w',$current_date),$working_days)){
//当前日期不是工作日
//当前时间戳在工作日开始时设置
$current_date=mktime($beg_h,$beg_m,0,日期($n',$current_date),日期($j',$current_date),日期($Y',$current_date));
//搜索下一个工作日
而(!在数组中(日期('w',$当前日期),$工作日)){
$current_date+=24*3600;//第二天
}
}否则{
//检查当前时间戳是否在工作时间内
$date0=mktime($beg_h,$beg_m,0,日期($n',$current_date),日期($j',$current_date),日期($Y',$current_date));
//在上班时间之前,让我们更新一下
如果($current_date$date3)$date2=$date3;
//计算从当前时间戳到最终时间戳的秒数
$tmp=$date2-$date0+1;
$seconds+=$tmp;
//printf(“
从%s到%s:%d小时
”,日期('d/m/y H:i',$date2),日期('d/m/y H:i',$date3),$tmp/3600); } //以秒为单位计算工作日 $seconds+=3600*($working_hours[1]-$working_hours[0])*$days; //printf(“
从%s到%s:%d小时
”,日期('d/m/y H:i',$date1),日期('d/m/y H:i',$date2),$seconds/3600); //返回$sign*$seconds/3600;//以获取小时数 返回回合(秒/3600美元); } 日期默认时区设置(“欧洲/伊斯坦布尔”); $dt2=标准时间(“29-12-2015 11:17:39”); $dt1=标准时间(“29-12-2015 13:17:43”); 回声工作时间差异($dt1,$dt2);
试试这个

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
替换此行:

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

如果
if
,这是错误的,因为它消除了$days值0和1之间的区别(在
if
之前),这是不正确的。

替换

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)
}

谢谢你的回答,但我必须计算没有周末,只包括日期之间的工作时间。您的代码只是计算日期之间的所有小时数。work_hours_diff函数适用于我,但当我输入不同时间的同一日期时,它无法正确计算。但是,如果我输入不同的日期,它会正确计算。我只是想解决这个问题。一个关于另一个问题答案的问题,让我们小心不要制造黑洞。
if (in_array(date('w',$date2) , $working_days)) {
    $days--; //because we've allready count the first day (in $seconds)
}