背景
之前做需求的时候需要判断两个时间段有没有交集,如果是没有交集就返回 true,否则就返回 false,主要的方法就是传入要添加的时间范围:[start, end],以及一个 List 集合,判断这个时间范围和这个 List 集合的时间范围有没有交集。
注意:end 如果为空,就表示时间范围是 [start, 无限)
思路和代码
现在我们设定一个时间类 TimeRange,包括 start 和 end 两个变量。
class TimeRange {
Long start;
Long end;
public TimeRange(Long start, Long end) {
this.start = start;
this.end = end;
}
@Override
public String toString() {
return "[" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(start)) + ", "
+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(end)) + "]";
}
}
我们首先看下两个没有交集的时间是怎么样的,看下面图示。
现在我们假设 TimeRange 里面的范围是 [start, range)
,也就是说如果 start2 >= end1
或者说 start1 >= end2
,这两种情况下两个时间段是没有交集的,用代码表示如下:
public boolean isConflict(TimeRange timeRange, List<TimeRange> sources) {
for (TimeRange source : sources) {
Long start1 = timeRange.start;
Long end1 = timeRange.end;
Long start2 = source.start;
Long end2 = source.end;
if (!(start2 >= end1 || start1 >= end2)) {
System.out.println("当前时间: " + timeRange.toString() + ", 冲突的时间段: " + source.toString());
return true;
}
}
return false;
}
下面我们来测试一下,我们随便生成 5 个时间传入 sources 中,接着测试有冲突和没有冲突的情况,当然生成的方法直接用 GPT。
// 生成随机的时间范围
private static TimeRange generateRandomTimeRange() {
Random random = new Random();
long startTime = System.currentTimeMillis() + random.nextInt(1000 * 60 * 60 * 24 * 7); // 未来一周内的随机起始时间
long endTime = startTime + random.nextInt(1000 * 60 * 60 * 2); // 起始时间往后最多两小时的随机结束时间
return new TimeRange(startTime, endTime);
}
// 生成有冲突的时间范围
private static TimeRange generateConflictingTimeRange(TimeRange existingRange) {
Random random = new Random();
long startOffset = random.nextInt((int) (existingRange.end - existingRange.start));
long startTime = existingRange.start + startOffset;
long endTime = startTime + random.nextInt(1000 * 60 * 60); // 随机结束时间,最长一小时
return new TimeRange(startTime, endTime);
}
来看下里面的 main 方法。
public class Main {
public static void main(String[] args) {
Main checker = new Main();
List<TimeRange> sources = new ArrayList<>();
// 生成 5 个随机的时间范围放入 sources 中
for (int i = 0; i < 5; i++) {
sources.add(generateRandomTimeRange());
}
// 测试无冲突的情况
TimeRange nonConflictingRange = generateRandomTimeRange();
boolean nonConflictResult = checker.isConflict(nonConflictingRange, sources);
System.out.println("Non - conflicting test:");
System.out.println("TimeRange: " + nonConflictingRange);
System.out.println("Sources: " + sources);
System.out.println("Is Conflict: " + nonConflictResult);
System.out.println();
// 测试有冲突的情况
TimeRange conflictingRange = generateConflictingTimeRange(sources.get(0));
boolean conflictResult = checker.isConflict(conflictingRange, sources);
System.out.println("Conflicting test:");
System.out.println("TimeRange: " + conflictingRange);
System.out.println("Sources: " + sources);
System.out.println("Is Conflict: " + conflictResult);
}
}
输出结果如下:
Non - conflicting test:
TimeRange: [2025-03-12 19:55:50, 2025-03-12 21:16:59]
Sources: [[2025-03-09 23:57:21, 2025-03-10 01:34:11], [2025-03-11 12:50:46, 2025-03-11 13:23:38], [2025-03-15 08:08:31, 2025-03-15 09:25:19], [2025-03-14 02:35:50, 2025-03-14 03:57:35], [2025-03-15 13:26:51, 2025-03-15 14:32:48]]
Is Conflict: false
当前时间: [2025-03-10 00:13:15, 2025-03-10 00:52:10], 冲突的时间段: [2025-03-09 23:57:21, 2025-03-10 01:34:11]
Conflicting test:
TimeRange: [2025-03-10 00:13:15, 2025-03-10 00:52:10]
Sources: [[2025-03-09 23:57:21, 2025-03-10 01:34:11], [2025-03-11 12:50:46, 2025-03-11 13:23:38], [2025-03-15 08:08:31, 2025-03-15 09:25:19], [2025-03-14 02:35:50, 2025-03-14 03:57:35], [2025-03-15 13:26:51, 2025-03-15 14:32:48]]
Is Conflict: true
但是有些情况下一个时间段 start 是肯定不为空的,而 end 可能为空,意味者时间段是: [ s t a r t , + ∞ ) [start, +\infty ) [start,+∞),这种情况下,我们可以将 end 设置为 Long.MAX_VALUE,也就是下面的写法。
public boolean isConflict(TimeRange timeRange, List<TimeRange> sources) {
if(timeRange.start == null){
throw new IllegalArgumentException("起始时间不能为空");
}
for (TimeRange source : sources) {
Long start1 = timeRange.start;
Long end1 = timeRange.end == null ? Long.MAX_VALUE : timeRange.end;
Long start2 = source.start;
Long end2 = source.end == null ? Long.MAX_VALUE : source.end;
if (!(start2 >= end1 || start1 >= end2)) {
System.out.println("当前时间: " + timeRange.toString() + ", 冲突的时间段: " + source.toString());
return true;
}
}
return false;
}
整体代码
public class Main {
public static void main(String[] args) {
Main checker = new Main();
List<TimeRange> sources = new ArrayList<>();
// 生成 5 个随机的时间范围放入 sources 中
for (int i = 0; i < 5; i++) {
sources.add(generateRandomTimeRange());
}
// 测试无冲突的情况
TimeRange nonConflictingRange = generateRandomTimeRange();
boolean nonConflictResult = checker.isConflict(nonConflictingRange, sources);
System.out.println("Non - conflicting test:");
System.out.println("TimeRange: " + nonConflictingRange);
System.out.println("Sources: " + sources);
System.out.println("Is Conflict: " + nonConflictResult);
System.out.println();
// 测试有冲突的情况
TimeRange conflictingRange = generateConflictingTimeRange(sources.get(0));
boolean conflictResult = checker.isConflict(conflictingRange, sources);
System.out.println("Conflicting test:");
System.out.println("TimeRange: " + conflictingRange);
System.out.println("Sources: " + sources);
System.out.println("Is Conflict: " + conflictResult);
}
public boolean isConflict(TimeRange timeRange, List<TimeRange> sources) {
if(timeRange.start == null){
throw new IllegalArgumentException("起始时间不能为空");
}
for (TimeRange source : sources) {
Long start1 = timeRange.start;
Long end1 = timeRange.end == null ? Long.MAX_VALUE : timeRange.end;
Long start2 = source.start;
Long end2 = source.end == null ? Long.MAX_VALUE : source.end;
if (!(start2 >= end1 || start1 >= end2)) {
System.out.println("当前时间: " + timeRange.toString() + ", 冲突的时间段: " + source.toString());
return true;
}
}
return false;
}
// 生成随机的时间范围
private static TimeRange generateRandomTimeRange() {
Random random = new Random();
long startTime = System.currentTimeMillis() + random.nextInt(1000 * 60 * 60 * 24 * 7); // 未来一周内的随机起始时间
long endTime = startTime + random.nextInt(1000 * 60 * 60 * 2); // 起始时间往后最多两小时的随机结束时间
return new TimeRange(startTime, endTime);
}
// 生成有冲突的时间范围
private static TimeRange generateConflictingTimeRange(TimeRange existingRange) {
Random random = new Random();
long startOffset = random.nextInt((int) (existingRange.end - existingRange.start));
long startTime = existingRange.start + startOffset;
long endTime = startTime + random.nextInt(1000 * 60 * 60); // 随机结束时间,最长一小时
return new TimeRange(startTime, endTime);
}
}
class TimeRange {
Long start;
Long end;
public TimeRange(Long start, Long end) {
this.start = start;
this.end = end;
}
@Override
public String toString() {
return "[" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(start)) + ", "
+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(end)) + "]";
}
}
如有错误,欢迎指出!!!