无论上午/下午如何,如何检查时间段是否与另一个时间段重叠 [英] How to check if time period is overlapping another time period irrespective of AM/PM

查看:47
本文介绍了无论上午/下午如何,如何检查时间段是否与另一个时间段重叠的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下链接:如何在java中检查一个时间段是否与另一个时间段重叠有助于检查给定的时间戳是否与另一个时间戳重叠.

但是,这仅在两个时间戳位于 AMPM 时才有效.我想检查的是,给定的时间戳是否与另一个时间戳重叠,而不管它是在 AM 还是 PM.

例如:如果我有一个 Array 时间戳(24 小时格式):

1:00 - 3:0013:45 - 14:453:15 - 4:00.

前两个在技术上是重叠的,因为 13:45 - 14:45 落在 1:00-3:00 之间(如果转换为 12 小时格式)

我如何检查是否相同?我想基本上检查时间戳(+/- 30 分钟)之间是否有任何重叠

解决方案

假设每个区间在 AM 或 PM 之内

我假设每个时间间隔完全在上午(00:00 到 12 点)或下午(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);//将间隔 1 转换为 AMif (begin1.get(ChronoField.AMPM_OF_DAY) == 1) {//下午begin1 = begin1.minusHours(12);end1 = end1.minusHours(12);}//证实如果 (end1.isBefore(begin1)) {throw new IllegalStateException("end1 " + end1 + " 不能在 begin1 " + begin1 之前);}如果(end1.isAfter(LocalTime.NOON)){throw new IllegalStateException("间隔 1 必须完全在 AM 或 PM 内");}//将间隔 2 转换为 AM如果 (begin2.get(ChronoField.AMPM_OF_DAY) == 1) {begin2 = begin2.minusHours(12);end2 = end2.minusHours(12);}//证实如果 (end2.isBefore(begin2)) {throw new IllegalStateException("end2 " + end2 + " 不能在 begin2 " + begin2 之前);}如果(end2.isAfter(LocalTime.NOON)){throw new IllegalStateException("间隔 2 必须完全在 AM 或 PM 内");}if (end2.isAfter(begin1) && end1.isAfter(begin2)) {System.out.println("它们重叠");} 别的 {System.out.println("它们不重叠");}

此代码的输出为:

<块引用>

它们重叠

特殊情况:我接受 AM 间隔的结束时间为 12:00(中午),PM 间隔的结束时间为 00:00.LocalTime.minusHours() 有循环下溢,所以从 00:00 减去 12 小时得到 12:00.

如果您定义一个带有开始和结束字段的 TimePeriod 类、一个检查重叠的方法和一个转换为 AM 的辅助方法,代码可能会更简单、更容易找到.

没有限制

假设每个间隔可以是从 0(含)到 24 小时(不含)的任意长度,并且可能跨越 00:00,这有点复杂,但我不能让挑战休息.

一些观察:

  1. 如果一个时间间隔为 12 小时或更长,而另一个时间间隔不为零,则两者必然重叠.
  2. 如果两个时间间隔都小于 12 小时,那么如果它们不重叠,我们可以从 begin1end1begin2 循环前进(计数)end2 按照这里给出的顺序 要么 不越过 12 点 要么 一次越过 12 点并在 begin1.如果这个循环不起作用,那么间隔必须以某种方式重叠.

在代码中:

public static boolean重叠(LocalTime begin1, LocalTime end1, LocalTime begin2, LocalTime end2) {if (begin1.equals(end1)) {//零长度,不能重叠任何东西返回假;}如果(begin2.equals(end2)){返回假;}//如果任何间隔是 12 小时或更长,//另一个是必然包含的,即重叠如果 (is12HoursOrLonger(begin1, end1)) {返回真;}如果 (is12HoursOrLonger(begin2, end2)) {返回真;}//将所有时间转换为 AMbegin1 = toAm(begin1);end1 = toAm(end1);begin2 = toAm(begin2);end2 = toAm(end2);//为了让两个区间*不*重叠,我们必须能够前进//按照这个顺序从 begin1 到 end1 和 begin2 到 end2//不跨越 12 或跨越 12 一次并在 begin1 之前或之前结束boolean crossed12OClock = false;if (end1.isBefore(begin1)) {//前进到 end1 我们正穿过 12 点钟crossed12Olock = 真;}如果 (begin2.isBefore(end1)) {如果(交叉12Olock){//第二次穿越 12;//间隔不能按非重叠顺序返回真;}crossed12Olock = 真;}如果 (end2.isBefore(begin2)) {如果(交叉12Olock){返回真;}crossed12Olock = 真;}如果(交叉12Olock){返回 end2.isAfter(begin1);} 别的 {返回假;}}

该方法使用了以下两个辅助方法:

private static boolean is12HoursOrLonger(LocalTime begin, LocalTime end) {持续时间长度 = Duration.between(begin, end);如果(长度.isNegative()){长度 = length.plusDays(1);}返回 !length.minusHours(12).isNegative();}私有静态 LocalTime toAm(LocalTime time) {返回 time.with(ChronoField.AMPM_OF_DAY, 0);}

让我们用之前的时间试试:

 if (overlaps(begin1, end1, begin2, end2)) {System.out.println("它们重叠");} 别的 {System.out.println("它们不重叠");}

<块引用>

它们重叠

由于代码和参数很复杂,请确保通过单元测试彻底覆盖方法.

The following link: How to check a timeperiod is overlapping another time period in java is helpful to check if a given timestamp overlaps with another timestamp.

However, this only works if the two timestamp are either in AM or PM. What I want to check is, if a given timestamp is overlapping another timestamp irrespective if it's in AM or PM.

For example: If I have an Array of timestamps (in 24 hour format):

1:00 - 3:00

13:45 - 14:45

3:15 - 4:00.

The first two are technically overlapping since 13:45 - 14:45 falls between 1:00-3:00 (if converted into 12 hour format)

How do I check for the same? I want to essentially check if there is any overlap between the timestamps (+/- 30 mins)

解决方案

Assuming that each interval is within either AM or PM

I am assuming that each interval is either completely within AM (00:00 through 12) or PM (12:00 through 00). I didn’t understand what you meant by "(+/- 30 mins)", so I have ignored that.

As an aside I consider this an artificial challenge. In the real world 2 AM and 2 PM are not the same, they just happen to have identical representations on a 12 hour clock. Just as a flag pole and a person from Poland are not the same even though they both have the representation "Pole".

As Sweeper suggested in a comment I am converting each interval to AM (if it was in PM) before comapring.

    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");
    }

Output from this code is:

They overlap

Corner case: I am accepting an end time of 12:00 (noon) for an AM interval and of 00:00 for a PM interval. LocalTime.minusHours() has cyclic underflow, so subtracting 12 hours from 00:00 gives 12:00.

The code may be simpler and easier to find your way through if you define a TimePeriod class with fields for begin and end, a method for checking overlap and an auxiliary method for converting into AM.

With no restrictions

Edit: Assuming that each interval can be any length from 0 (inclusive) to 24 hours (exclusive) and may cross 00:00, this is somewhat more complicated, but I couldn’t let the challenge rest.

Some observations:

  1. If one interval is 12 hours or longer and the other has non-zero length, the two necessarily overlap.
  2. If both intervals are shorter than 12 hours, then if they do not overlap, we can go (count) cyclically forward from begin1 through end1 and begin2 to end2 in the order given here and either not cross 12 o’clock or cross 12 once and end up before begin1. If this cycle doesn’t work, then the intervals must overlap somehow.

In code:

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;
    }
}

This method uses the following two auxiliary methods:

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);
}

Let’s try it out using the times from before:

    if (overlaps(begin1, end1, begin2, end2)) {
        System.out.println("They overlap");
    } else {
        System.out.println("They do not overlap");
    }

They overlap

Since the code and the arguments are complicated, make sure to cover the methods thoroughly with unit tests.

这篇关于无论上午/下午如何,如何检查时间段是否与另一个时间段重叠的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆