PHP DateTime计算时间差 如何判断签到提前或延后的分钟数
问题原因
DateTime::diff() 返回的DateInterval对象默认存储的是时间差的绝对值,所以无论怎么调换两个时间的顺序,用%i格式化输出的分钟数值都不会变,无法直接体现时间先后。
时间的先后方向实际存在DateInterval的invert属性中:
invert值为0:调用diff方法的时间对象晚于传入的对比时间invert值为1:调用diff方法的时间对象早于传入的对比时间
可行实现方案
方案1:利用invert属性判断方向
需要注意单独读取%i只能拿到分钟段的差值,跨小时、跨天的场景要同步换算小时、天数为分钟,否则计算结果会出错:
<?php $starttime = new DateTime('2022-06-07 00:10:00'); // 规定签到开始时间 $checkin = new DateTime('2022-06-07 00:30:00'); // 用户实际签到时间 $interval = $starttime->diff($checkin); // 换算总分钟差 $totalMinutes = $interval->days * 24 * 60 + $interval->h * 60 + $interval->i; // 实际签到时间早于规定时间,差值为负代表提前 if ($interval->invert) { $totalMinutes = -$totalMinutes; } // 业务逻辑判断 if ($totalMinutes < 0 && abs($totalMinutes) >= 15) { echo "用户提前" . abs($totalMinutes) . "分钟签到"; } elseif ($totalMinutes >= 0 && $totalMinutes <= 15) { echo "用户准点签到"; } else { echo "用户延后" . $totalMinutes . "分钟签到"; } ?>
方案2:时间戳直接计算(推荐)
直接通过时间戳计算秒级差值再换算为分钟,天然自带正负方向,不需要额外处理方向标识,也不会出现跨时段换算错误的问题,代码更简洁:
<?php $starttime = new DateTime('2022-06-07 00:10:00'); // 规定签到开始时间 $checkin = new DateTime('2022-06-07 00:30:00'); // 用户实际签到时间 // 计算带方向的分钟差:结果为负=提前,为正=延后 $diffMinutes = (int)round(($checkin->getTimestamp() - $starttime->getTimestamp()) / 60); // 业务逻辑判断 if ($diffMinutes < 0 && abs($diffMinutes) >= 15) { echo "用户提前" . abs($diffMinutes) . "分钟签到"; } elseif ($diffMinutes >= 0 && $diffMinutes <= 15) { echo "用户准点签到"; } else { echo "用户延后" . $diffMinutes . "分钟签到"; } ?>
代码测试效果:
- 签到时间为
2022-06-07 00:00:00时,输出用户提前10分钟签到 - 签到时间为
2022-06-07 00:20:00时,输出用户准点签到 - 签到时间为
2022-06-07 00:30:00时,输出用户延后20分钟签到
内容的提问来源于stack exchange,提问作者sivashanker
相关产品推荐
相关产品推荐

