无法计算工时占比,求MySQL+PHP时间计算解决方案
问题根源与解决方案
我一眼就看出问题出在哪了——你直接把TIME格式的字符串拿来做加法运算了,这在PHP里会导致完全不符合预期的结果!
为什么会得到错误的12?
PHP在处理字符串加法时,会自动尝试把字符串转换为整数。比如你用的"02:02:00",PHP只会读取第一个冒号前的数字(也就是小时部分2),剩下的:02:00会被直接忽略。你代码里加了6个这样的数值,2+2+2+2+2+2=12,这就是你看到Calc 1: 12的原因,完全没有计算分钟和秒的部分。
下面给你两种靠谱的解决方案,任选其一就行:
方案一:在SQL中直接计算非工作时间总和
既然你已经在SQL里做了各类型时间的求和,不如直接在SQL里把非工作时间的总和算出来,这样PHP只需要直接读取结果,完全避免字符串转换的问题。
修改你的SQL语句,把需要求和的非工作时间字段转成秒后相加,再转回TIME格式:
$sql = "SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(`workhours`))) AS totalworkhours, SEC_TO_TIME(SUM(TIME_TO_SEC(`phonecall`))) AS totalphonecall, SEC_TO_TIME(SUM(TIME_TO_SEC(`meeting`))) AS totalmeeting, SEC_TO_TIME(SUM(TIME_TO_SEC(`coffe`))) AS totalcoffe, SEC_TO_TIME(SUM(TIME_TO_SEC(`education`))) AS totaleducation, SEC_TO_TIME(SUM(TIME_TO_SEC(`clean`))) AS totalclean, -- 计算非工作时间总和:对应代码里的$per_coffe、$per_clean、$other1-$other4 SEC_TO_TIME(SUM( TIME_TO_SEC(`coffe`) + TIME_TO_SEC(`clean`) + TIME_TO_SEC(`phonecall`) + TIME_TO_SEC(`meeting`) + TIME_TO_SEC(`education`) )) AS totalnonwork FROM working WHERE sheet_id = '$working_id'";
之后在PHP里直接取$row['totalnonwork'],就能得到正确的非工作时间总和(比如12:12:00)。
方案二:在PHP中转换为秒数后计算
如果不想修改SQL,那你需要先把每个TIME字符串转换成秒数,相加后再转成时间格式。
先写一个辅助函数用来转换时间到秒:
function timeToSeconds($timeStr) { // 把时间字符串拆成小时、分钟、秒 list($hours, $minutes, $seconds) = explode(':', $timeStr); return ($hours * 3600) + ($minutes * 60) + $seconds; }
然后修改你的计算代码:
// 把每个非工作时间转成秒 $coffeSec = timeToSeconds($per_coffe); $cleanSec = timeToSeconds($per_clean); $other1Sec = timeToSeconds($other1); $other2Sec = timeToSeconds($other2); $other3Sec = timeToSeconds($other3); $other4Sec = timeToSeconds($other4); // 计算总秒数 $totalNonWorkSec = $coffeSec + $cleanSec + $other1Sec + $other2Sec + $other3Sec + $other4Sec; // 转成带小时/分钟/秒的格式(支持超过24小时的情况) $hours = floor($totalNonWorkSec / 3600); $minutes = floor(($totalNonWorkSec % 3600) / 60); $seconds = $totalNonWorkSec % 60; $totalNonWorkTime = sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds); echo "Calc 1: ". $totalNonWorkTime ."<br />";
这样就能得到正确的12:12:00了。
计算实际工时占比
得到正确的非工作时间后,计算实际工时占比就很简单了:
// 把总工时也转成秒 $totalWorkSec = timeToSeconds($row['totalworkhours']); // 实际工时秒数 = 总工时秒数 - 非工作时间秒数 $actualWorkSec = $totalWorkSec - $totalNonWorkSec; // 计算占比(保留两位小数) $percentage = ($actualWorkSec / $totalWorkSec) * 100; echo "实际工时占比:". number_format($percentage, 2) ."%<br />";
内容的提问来源于stack exchange,提问作者andernicken
相关产品推荐
相关产品推荐

