如何将指定时间范围集合从另一个时间范围集合中移除?
实现思路
- 先把所有时间字符串转为时间戳,避免字符串直接比对的格式兼容问题,提升比较效率
- 遍历第二组xyz的每一个时间范围,和第一组abc的所有待排除时间范围逐一做重叠校验
- 针对不同重叠场景做对应切割处理:
- 无重叠:直接保留原xyz时间范围
- 待排除范围完全覆盖当前xyz范围:直接丢弃该段xyz时间
- 待排除范围和xyz开头重叠:保留xyz中待排除结束时间到原xyz结束时间的部分
- 待排除范围和xyz结尾重叠:保留xyz开始时间到待排除开始时间的部分
- 待排除范围完全在xyz内部:切割为前后两段保留
- 汇总所有处理后的有效时间范围即为最终结果
JavaScript 实现代码
// 时间字符串转时间戳 function toTimestamp(timeStr) { return new Date(timeStr).getTime(); } function subtractTimeRanges(xyz, abc) { let result = JSON.parse(JSON.stringify(xyz)); // 遍历所有要排除的时间范围 for (const exclude of abc) { const excludeStart = toTimestamp(exclude.start); const excludeEnd = toTimestamp(exclude.end); const tempResult = []; // 逐段处理当前保留的时间 for (const range of result) { const rangeStart = toTimestamp(range.start); const rangeEnd = toTimestamp(range.end); // 完全不重叠直接保留 if (excludeEnd <= rangeStart || excludeStart >= rangeEnd) { tempResult.push({...range}); continue; } // 待排除段完全覆盖当前段,直接丢弃 if (excludeStart <= rangeStart && excludeEnd >= rangeEnd) { continue; } // 重叠开头,保留后半段 if (excludeStart <= rangeStart && excludeEnd < rangeEnd) { tempResult.push({ start: new Date(excludeEnd).toISOString().slice(0, 19).replace('T', ' '), end: range.end }); continue; } // 重叠结尾,保留前半段 if (excludeStart > rangeStart && excludeEnd >= rangeEnd) { tempResult.push({ start: range.start, end: new Date(excludeStart).toISOString().slice(0, 19).replace('T', ' ') }); continue; } // 待排除段在中间,拆为两段 if (excludeStart > rangeStart && excludeEnd < rangeEnd) { tempResult.push({ start: range.start, end: new Date(excludeStart).toISOString().slice(0, 19).replace('T', ' ') }); tempResult.push({ start: new Date(excludeEnd).toISOString().slice(0, 19).replace('T', ' '), end: range.end }); } } result = tempResult; } return result; } // 测试用例 const abc = [{"start": "2021-11-25 16:30:00", "end": "2021-11-25 17:30:00"}]; const xyz = [ {"start": "2021-11-25 09:00:00", "end": "2021-11-25 18:00:00"}, {"start": "2021-11-26 15:00:00", "end": "2021-11-26 19:00:00"} ]; console.log(subtractTimeRanges(xyz, abc));
PHP 实现代码
// 时间字符串转时间戳 function toTimestamp(string $timeStr): int { return strtotime($timeStr); } function subtractTimeRanges(array $xyz, array $abc): array { $result = json_decode(json_encode($xyz), true); foreach ($abc as $exclude) { $excludeStart = toTimestamp($exclude['start']); $excludeEnd = toTimestamp($exclude['end']); $tempResult = []; foreach ($result as $range) { $rangeStart = toTimestamp($range['start']); $rangeEnd = toTimestamp($range['end']); // 完全不重叠直接保留 if ($excludeEnd <= $rangeStart || $excludeStart >= $rangeEnd) { $tempResult[] = $range; continue; } // 待排除段完全覆盖当前段,直接丢弃 if ($excludeStart <= $rangeStart && $excludeEnd >= $rangeEnd) { continue; } // 重叠开头,保留后半段 if ($excludeStart <= $rangeStart && $excludeEnd < $rangeEnd) { $tempResult[] = [ 'start' => date('Y-m-d H:i:s', $excludeEnd), 'end' => $range['end'] ]; continue; } // 重叠结尾,保留前半段 if ($excludeStart > $rangeStart && $excludeEnd >= $rangeEnd) { $tempResult[] = [ 'start' => $range['start'], 'end' => date('Y-m-d H:i:s', $excludeStart) ]; continue; } // 待排除段在中间,拆为两段 if ($excludeStart > $rangeStart && $excludeEnd < $rangeEnd) { $tempResult[] = [ 'start' => $range['start'], 'end' => date('Y-m-d H:i:s', $excludeStart) ]; $tempResult[] = [ 'start' => date('Y-m-d H:i:s', $excludeEnd), 'end' => $range['end'] ]; } } $result = $tempResult; } return $result; } // 测试用例 $abc = [['start' => '2021-11-25 16:30:00', 'end' => '2021-11-25 17:30:00']]; $xyz = [ ['start' => '2021-11-25 09:00:00', 'end' => '2021-11-25 18:00:00'], ['start' => '2021-11-26 15:00:00', 'end' => '2021-11-26 19:00:00'] ]; var_dump(subtractTimeRanges($xyz, $abc));
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

