环境:tp8.0, php8.3, nesbot/carbon3.11;
php
/**
* 通用签到/签退方法
*
* @param string $type 打卡类型 'in'=签到, 'out'=签退
* @param string $signInTime 规则签到时间,格式 'H:i:s'
* @param string $signOutTime 规则签退时间,格式 'H:i:s'
* @return Json
*/
public function signInOut(string $type, string $signInTime, string $signOutTime): Json
{
$date = Carbon::today()->toDateString();
// 规则时间转 Carbon
$ruleSignIn = Carbon::parse("$date $signInTime");
$ruleSignOut = Carbon::parse("$date $signOutTime");
$now = Carbon::parse('2026-3-23 11:59:59');
// 使用 match 简化 if/elseif
$data = match ($type) {
'in' => [
'lateMinutes' => $now->gt($ruleSignIn) ? (int) ceil($ruleSignIn->diffInSeconds($now) / 60) : 0,
'signInStatus' => $now->gt($ruleSignIn)
? '迟到 ' . (int) ceil($ruleSignIn->diffInSeconds($now) / 60) . ' 分钟'
: '正常签到',
],
'out' => [
'earlyMinutes' => $now->lt($ruleSignOut) ? (int) ceil($now->diffInSeconds($ruleSignOut) / 60) : 0,
'signOutStatus' => $now->lt($ruleSignOut)
? '早退 ' . (int) ceil($now->diffInSeconds($ruleSignOut) / 60) . ' 分钟'
: '正常签退',
],
default => null
};
if ($data === null) {
return json([
'code' => 400,
'msg' => '打卡类型错误,必须是 in 或 out',
'data' => []
]);
}
return json(['code' => 200, 'msg' => 'success', 'data' => $data]);
}
php
/**
* 判断两个日期区间是否冲突
*
* @param array $date1 [start, end]
* @param array $date2 [start, end]
* @return bool|Json
*/
public function timeConflict(array $date1, array $date2): bool|Json
{
// 参数校验
if (count($date1) !== 2 || count($date2) !== 2) {
return json(['code'=>400, 'msg'=>'参数格式错误', 'data'=>[]]);
}
[$start1, $end1] = $date1;
[$start2, $end2] = $date2;
// 转 Carbon(按天)
$start1 = Carbon::parse($start1)->startOfDay();
$end1 = Carbon::parse($end1)->endOfDay();
$start2 = Carbon::parse($start2)->startOfDay();
$end2 = Carbon::parse($end2)->endOfDay();
// 核心判断:是否重叠
return $start1->lte($end2) && $start2->lte($end1);
}