如何检查时间段是否与另一个时间段重叠,而与AM / PM无关
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何检查时间段是否与另一个时间段重叠,而与AM / PM无关相关的知识,希望对你有一定的参考价值。
以下链接:How to check a timeperiod is overlapping another time period in java有助于检查给定的时间戳是否与另一个时间戳重叠。
但是,仅当两个时间戳位于AM
或PM
中时,此方法才有效。我要检查的是,给定的时间戳是否与另一个时间戳重叠,无论它位于AM
还是PM
中。
例如:如果我有Array
时间戳(以24小时格式):
1:00 - 3:00
13:45 - 14:45
3:15 - 4:00.
前两个在技术上是重叠的,因为13:45-14:45在1:00-3:00之间(如果转换为12小时格式)
我该如何检查?我基本上想检查时间戳之间是否有重叠(+/- 30分钟)
假设每个间隔都在AM或PM之内
我假设每个间隔完全在AM(00:00到12)或PM(12:00到00)之内。我不明白您的意思是“(+/- 30分钟)”,所以我忽略了这一点。
此外,我认为这是人为的挑战。在现实世界中,“凌晨2点”和“下午2点”并不相同,它们恰好在12小时时钟上具有相同的表示。就像旗杆和波兰人都不一样,即使他们都用“ Pole”表示。
如Sweeper在评论中所建议,我将每个时间间隔在共同映射之前转换为AM(如果在PM中)。
LocalTime begin1 = LocalTime.of(1, 0);
LocalTime end1 = LocalTime.of(3, 0);
LocalTime begin2 = LocalTime.of(13, 45);
LocalTime end2 = LocalTime.of(14, 45);
// Convert interval 1 to AM
if (begin1.get(ChronoField.AMPM_OF_DAY) == 1) { // PM
begin1 = begin1.minusHours(12);
end1 = end1.minusHours(12);
}
// validate
if (end1.isBefore(begin1)) {
throw new IllegalStateException("end1 " + end1 + " must not be before begin1 " + begin1);
}
if (end1.isAfter(LocalTime.NOON)) {
throw new IllegalStateException("Interval 1 must be completely within either AM or PM");
}
// Convert interval 2 to AM
if (begin2.get(ChronoField.AMPM_OF_DAY) == 1) {
begin2 = begin2.minusHours(12);
end2 = end2.minusHours(12);
}
// validate
if (end2.isBefore(begin2)) {
throw new IllegalStateException("end2 " + end2 + " must not be before begin2 " + begin2);
}
if (end2.isAfter(LocalTime.NOON)) {
throw new IllegalStateException("Interval 2 must be completely within either AM or PM");
}
if (end2.isAfter(begin1) && end1.isAfter(begin2)) {
System.out.println("They overlap");
} else {
System.out.println("They do not overlap");
}
此代码的输出是:
它们重叠
[正确的情况:对于AM间隔,我接受12:00(中午)的结束时间,对于PM间隔,我接受00:00的结束时间。 LocalTime.minusHours()
具有周期性下溢,因此从00:00减去12小时可得出12:00。
如果您定义一个TimePeriod
类,其中包含用于开始和结束的字段,一种用于检查重叠的方法以及一种用于转换为AM的辅助方法,则该代码可能会更容易找到,并且更容易找到代码。
无限制
编辑:假设每个时间间隔可以是0(包括0)到24小时(不包括)之间的任何长度,并且可以跨越00:00,这有点复杂,但是我无法接受挑战。
一些观察:
- 如果一个间隔为12小时或更长时间,而另一个间隔的长度不为零,则这两个间隔必定重叠。
- [如果两个时间间隔都短于12小时,那么如果它们不重叠,我们可以按照此处给定的顺序从
begin1
到end1
和begin2
循环到end2
(要么 不越过12点或越过12次并在
begin1
之前结束。如果此循环不起作用,则间隔必须以某种方式重叠。使用代码:
public static boolean overlaps(LocalTime begin1, LocalTime end1, LocalTime begin2, LocalTime end2) { if (begin1.equals(end1)) { // zero length, cannot overlap anything return false; } if (begin2.equals(end2)) { return false; } // If any interval is 12 hours or longer, // the other one is necessarily included, that is, overlaps if (is12HoursOrLonger(begin1, end1)) { return true; } if (is12HoursOrLonger(begin2, end2)) { return true; } // Convert all times to AM begin1 = toAm(begin1); end1 = toAm(end1); begin2 = toAm(begin2); end2 = toAm(end2); // For the two intervals *not* to overlap we must be able to go forward // from begin1 through end1 and begin2 to end2 in this order either // not crossing 12 or crossing 12 once and ending before or on begin1 boolean crossed12OClock = false; if (end1.isBefore(begin1)) { // to go forward to end1 we are crossing 12 o’clock crossed12OClock = true; } if (begin2.isBefore(end1)) { if (crossed12OClock) { // crossing 12 for the second time; // intervals cannot be in non-overlapping order return true; } crossed12OClock = true; } if (end2.isBefore(begin2)) { if (crossed12OClock) { return true; } crossed12OClock = true; } if (crossed12OClock) { return end2.isAfter(begin1); } else { return false; } }
此方法使用以下两种辅助方法:
private static boolean is12HoursOrLonger(LocalTime begin, LocalTime end) { Duration length = Duration.between(begin, end); if (length.isNegative()) { length = length.plusDays(1); } return ! length.minusHours(12).isNegative(); } private static LocalTime toAm(LocalTime time) { return time.with(ChronoField.AMPM_OF_DAY, 0); }
让我们使用以前的时间尝试一下:
if (overlaps(begin1, end1, begin2, end2)) { System.out.println("They overlap"); } else { System.out.println("They do not overlap"); }
它们重叠
以上是关于如何检查时间段是否与另一个时间段重叠,而与AM / PM无关的主要内容,如果未能解决你的问题,请参考以下文章