检查给定时间是否在两个时间之间,无论日期如何。

72

我有时间段:

String time1 = 01:00:00

String time2 = 05:00:00

我想要检查 time1time2 是否都在 20:11:13和14:49:00之间。

实际上,01:00:00 大于 20:11:13 且小于 14:49:00,考虑到 20:11:13 总是小于 14:49:00,这是前提条件。

所以我想要的是,20:11:13 < 01:00:00 < 14:49:00

因此我需要像这样的东西:

 public void getTimeSpans()
{
    boolean firstTime = false, secondTime = false;
    
    if(time1 > "20:11:13" && time1 < "14:49:00")
    {
       firstTime = true;
    }
    
    if(time2 > "20:11:13" && time2 < "14:49:00")
    {
       secondTime = true;
    }
 }

我知道这段代码不会得出正确的结果,因为我在比较字符串对象。

它们是时间跨度而不是要比较的字符串,那该怎么办呢?


4
如果不考虑日期,这怎么可能成立呢?如果时间大于20:11:13,它就不可能小于14:49:00。 - jalynn2
@jalynn2 - 抱歉没有表达清楚。实际上,01:00:00 大于 20:11:13 且小于 14:49:00,前提是 20:11:13 总是小于 14:49:00。这是给定的先决条件。 - My God
2
如果您提供的格式为HH:MM:SS,则在同一天内,01:00:00不比20:11:13更大,而20:11:13永远不会小于14:49:00。如果您想确定时间是否介于第一天的20:11:13和第二天的14:49:00之间,则需要在比较中引入日期。 - jalynn2
不考虑日期,因为20:11:13始终小于14:49:00,这样不是也可以吗? - My God
4
20比14大,不是吗?因此,“20:11:13”比“14:49:00”更大。在同一天内,“下午3点前11分钟”不比“晚上8点后11分钟”更晚。我错过了什么? - jalynn2
显示剩余3条评论
33个回答

69
你可以使用Calendar类来检查。
例如:
try {
    String string1 = "20:11:13";
    Date time1 = new SimpleDateFormat("HH:mm:ss").parse(string1);
    Calendar calendar1 = Calendar.getInstance();
    calendar1.setTime(time1);
    calendar1.add(Calendar.DATE, 1);


    String string2 = "14:49:00";
    Date time2 = new SimpleDateFormat("HH:mm:ss").parse(string2);
    Calendar calendar2 = Calendar.getInstance();
    calendar2.setTime(time2);
    calendar2.add(Calendar.DATE, 1);

    String someRandomTime = "01:00:00";
    Date d = new SimpleDateFormat("HH:mm:ss").parse(someRandomTime);
    Calendar calendar3 = Calendar.getInstance();
    calendar3.setTime(d);
    calendar3.add(Calendar.DATE, 1);

    Date x = calendar3.getTime();
    if (x.after(calendar1.getTime()) && x.before(calendar2.getTime())) {
        //checkes whether the current time is between 14:49:00 and 20:11:13.
        System.out.println(true);
    }
} catch (ParseException e) {
    e.printStackTrace();
}

2
那么你将不得不在某个地方标记这些时间不在同一天! - Konstantin Yovkov
1
除非您正在检查的时间是 23:00:00。否则,您需要有一个相关的日期,或者您需要检查该时间是否在 20:11:1324:00:00 之间或在 00:00:0014:49:00 之间。 - jalynn2
1
我也使用了以下代码进行剩余比较:Date currentTime = new SimpleDateFormat("HH:mm:ss").parse("00:00:00"); Calendar calendar = Calendar.getInstance(); calendar.setTime(currentTime); calendar.add(Calendar.DATE, 1);。让我检查一下完整的内容。 - My God
3
如果someRandomTime介于string1和"00:00:00"之间,那么这可能会给出错误答案。如果我错了请纠正我。 - Narayan Acharya
2
它显示的11:44在19:28到23:59之间...有什么解决办法吗? - Gundu Bandgar
显示剩余11条评论

58

简而言之

20:11:13 < 01:00:00 < 14:49:00

LocalTime target = LocalTime.parse( "01:00:00" ) ;
Boolean targetInZone = ( 
    target.isAfter( LocalTime.parse( "20:11:13" ) ) 
    && 
    target.isBefore( LocalTime.parse( "14:49:00" ) ) 
) ; 

java.time.LocalTime

java.time类包括LocalTime,用于表示仅有时间而没有日期和时区的时间。

所以我想要的是,20:11:13 < 01:00:00 < 14:49:00。

首先我们定义边界。您的输入字符串恰好符合标准ISO 8601格式。java.time类默认使用ISO 8601格式,因此无需指定格式模式。

LocalTime start = LocalTime.parse( "20:11:13" );
LocalTime stop = LocalTime.parse( "14:49:00" );

定义我们的测试用例,目标01:00:00

LocalTime target = LocalTime.parse( "01:00:00" );

现在我们已经准备好比较这些 LocalTime 对象。我们想要查看目标时间是否在较晚时间之后,但在较早时间之前。也就是说,在这种情况下是在半夜时分,大约在晚上8点到第二天早上3点之间。
Boolean isTargetAfterStartAndBeforeStop = ( target.isAfter( start ) && target.isBefore( stop ) ) ;

那个测试可以更简单地表述为“在凌晨3点到下午8点之间不是”。我们可以推广到任何一对LocalTime对象,如果开始时间早于结束时间且使用24小时制,则进行之间的测试,否则进行不在之间的测试(就像这个问题中的情况)。此外,时间段通常使用半开放方法处理,其中开始时间是包含的,而结束时间是排除的。因此,“之间”的比较严格来说应该是“目标是否等于或晚于开始时间并且目标在结束时间之前”,或者更简单地说,“目标不在开始时间之前且在结束时间之前”。
Boolean isBetweenStartAndStopStrictlySpeaking = 
    ( ( ! target.isBefore( start ) && target.isBefore( stop ) ) ;

如果开始时间晚于结束时间,在24小时制下,那么假设我们想要问题中建议的逻辑(即在晚上8点后但在凌晨3点前)。
if( start.isAfter( stop ) ) {
    return ! isBetweenStartAndStopStrictlySpeaking ;
} else {
    return isBetweenStartAndStopStrictlySpeaking ;
}

关于java.time

java.time框架内置于Java 8及更高版本中。这些类取代了老旧且麻烦的遗留日期时间类,如java.util.DateCalendarSimpleDateFormat

要了解更多,请参阅Oracle教程。并在Stack Overflow上搜索许多示例和解释。规范是JSR 310

Joda-Time项目现在处于维护模式,建议迁移到java.time类。

您可以直接使用数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC驱动程序。无需字符串,无需java.sql.*类。Hibernate 5和JPA 2.2支持java.time
在哪里获取java.time类?

这对于目标时间18:00不起作用,开始时间是21:00,结束时间是03:00。在这种情况下,目标时间不是在开始时间之前,但目标时间也不在结束时间之前。因此,isBetweenStartAndStopStrctlySpeaking为false。由于开始时间在结束时间之后,我们对其取反,这等同于说18:00在21:00和03:00之间,这是错误的。 - thisisananth
1
@thisisananth,您已经颠倒了问题的逻辑。问题明确要求目标是在较晚时间之后较早时间之前所以我想要的是,20:11:13 < 01:00:00 < 14:49:00。因此,在您的例子中,18:00(下午6点)不在21:00和03:00之间,而凌晨1点晚上9点和凌晨3点之间。无论您的业务逻辑规定哪种逻辑,请翻转我的代码的布尔逻辑。但是,您不能让凌晨1点和下午6点都处于深夜和清晨时段之间--这样问“是否介于”就没有意义了。 - Basil Bourque

24

@kocko提供的答案仅适用于同一天。
如果开始时间为"23:00:00",结束时间为"02:00:00"[第二天],当前时间为"01:30:00",则结果将为false...
我修改了@kocko的答案,使其完美运行。

public static boolean isTimeBetweenTwoTime(String initialTime, String finalTime, 
    String currentTime) throws ParseException {

    String reg = "^([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$";
    if (initialTime.matches(reg) && finalTime.matches(reg) && 
        currentTime.matches(reg)) 
    {
        boolean valid = false;
        //Start Time
        //all times are from java.util.Date
        Date inTime = new SimpleDateFormat("HH:mm:ss").parse(initialTime);
        Calendar calendar1 = Calendar.getInstance();
        calendar1.setTime(inTime);

        //Current Time
        Date checkTime = new SimpleDateFormat("HH:mm:ss").parse(currentTime);
        Calendar calendar3 = Calendar.getInstance();
        calendar3.setTime(checkTime);

        //End Time
        Date finTime = new SimpleDateFormat("HH:mm:ss").parse(finalTime);
        Calendar calendar2 = Calendar.getInstance();
        calendar2.setTime(finTime);

        if (finalTime.compareTo(initialTime) < 0) 
        {
            calendar2.add(Calendar.DATE, 1);
            calendar3.add(Calendar.DATE, 1);
        }

        java.util.Date actualTime = calendar3.getTime();
        if ((actualTime.after(calendar1.getTime()) || 
             actualTime.compareTo(calendar1.getTime()) == 0) && 
             actualTime.before(calendar2.getTime())) 
        {
            valid = true;
            return valid;
        } else {
            throw new IllegalArgumentException("Not a valid time, expecting 
            HH:MM:SS format");
        }
    }
}

输出

"07:00:00" - "17:30:00" - "15:30:00" [current] - true
"17:00:00" - "21:30:00" - "16:30:00" [current] - false
"23:00:00" - "04:00:00" - "02:00:00" [current] - true
"00:30:00" - "06:00:00" - "06:00:00" [current] - false 

(我已将下限值包括在 [上限值-1] 内)


1
这是最好的答案@Surendra Jnawali - lacas
1
如果当前时间大于开始时间且小于等于23:59:59,那么这也会失败,即使当前时间是23:40:00。 - Jitender Dev
2
@SurendraJnawali 当然,请尝试这个 "23:00:00" - "06:00:00" - "23:40:00" [current] - false。我还发布了一个答案来更新您的答案,当然所有信用归您。 - Jitender Dev
1
这个不正常工作!Jitender Dev 的已修正版本。 - misterti
更新:可怕的DateCalendar类在多年前被现代的JSR 310中定义的java.time类所取代。 - Basil Bourque
显示剩余2条评论

22

修改了@Surendra Jnawali的代码,但是它失败了。

如果当前时间是23:40:00,即大于开始时间并且小于等于23:59:59。

所有功劳归真正的所有者所有。

这就是应该的:这个可以完美地工作。

public static boolean isTimeBetweenTwoTime(String argStartTime,
            String argEndTime, String argCurrentTime) throws ParseException {
        String reg = "^([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$";
        //
        if (argStartTime.matches(reg) && argEndTime.matches(reg)
                && argCurrentTime.matches(reg)) {
            boolean valid = false;
            // Start Time
            java.util.Date startTime = new SimpleDateFormat("HH:mm:ss")
                    .parse(argStartTime);
            Calendar startCalendar = Calendar.getInstance();
            startCalendar.setTime(startTime);

            // Current Time
            java.util.Date currentTime = new SimpleDateFormat("HH:mm:ss")
                    .parse(argCurrentTime);
            Calendar currentCalendar = Calendar.getInstance();
            currentCalendar.setTime(currentTime);

            // End Time
            java.util.Date endTime = new SimpleDateFormat("HH:mm:ss")
                    .parse(argEndTime);
            Calendar endCalendar = Calendar.getInstance();
            endCalendar.setTime(endTime);

            //
            if (currentTime.compareTo(endTime) < 0) {

                currentCalendar.add(Calendar.DATE, 1);
                currentTime = currentCalendar.getTime();

            }

            if (startTime.compareTo(endTime) < 0) {

                startCalendar.add(Calendar.DATE, 1);
                startTime = startCalendar.getTime();

            }
            //
            if (currentTime.before(startTime)) {

                System.out.println(" Time is Lesser ");

                valid = false;
            } else {

                if (currentTime.after(endTime)) {
                    endCalendar.add(Calendar.DATE, 1);
                    endTime = endCalendar.getTime();

                }

                System.out.println("Comparing , Start Time /n " + startTime);
                System.out.println("Comparing , End Time /n " + endTime);
                System.out
                        .println("Comparing , Current Time /n " + currentTime);

                if (currentTime.before(endTime)) {
                    System.out.println("RESULT, Time lies b/w");
                    valid = true;
                } else {
                    valid = false;
                    System.out.println("RESULT, Time does not lies b/w");
                }

            }
            return valid;

        } else {
            throw new IllegalArgumentException(
                    "Not a valid time, expecting HH:MM:SS format");
        }

    }

结果

Comparing , Start Time /n    Thu Jan 01 23:00:00 IST 1970
Comparing , End Time /n      Fri Jan 02 02:00:00 IST 1970
Comparing , Current Time /n  Fri Jan 02 01:50:00 IST 1970
RESULT, Time lies b/w

17

这里有很多答案,但我想提供一个新的答案,它类似于Basil Bourque的答案,但是带有完整的代码示例。所以请查看下面的方法:

private static void checkTime(String startTime, String endTime, String checkTime) {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss", Locale.US);
    LocalTime startLocalTime = LocalTime.parse(startTime, formatter);
    LocalTime endLocalTime = LocalTime.parse(endTime, formatter);
    LocalTime checkLocalTime = LocalTime.parse(checkTime, formatter);

    boolean isInBetween = false;
    if (endLocalTime.isAfter(startLocalTime)) {
      if (startLocalTime.isBefore(checkLocalTime) && endLocalTime.isAfter(checkLocalTime)) {
          isInBetween = true;
      }
    } else if (checkLocalTime.isAfter(startLocalTime) || checkLocalTime.isBefore(endLocalTime)) {
        isInBetween = true;
    }

    if (isInBetween) {
        System.out.println("Is in between!");
    } else {
        System.out.println("Is not in between!");
    }
}

无论您是使用以下方式调用此方法:

checkTime("20:11:13", "14:49:00", "01:00:00");

或者使用:

checkTime("20:11:13", "14:49:00", "05:00:00");

结果将会是:

Is in between!

我尝试在我的Android应用中使用它,但它说只适用于Api26+,有人可以帮忙吗? - ansh sachdeva
更改为 Api26+ - Alex Mamo
1
@AlexMamo 当然它可以在API 26及以上版本上运行,但我想支持直到安卓棒棒糖(API 21)。 - ansh sachdeva
1
最佳且简单的答案 - uncle bob
1
感激不尽 - 这是最好的答案。 - user1819780
显示剩余3条评论

15
 Calendar now = Calendar.getInstance();

 int hour = now.get(Calendar.HOUR_OF_DAY); // Get hour in 24 hour format
 int minute = now.get(Calendar.MINUTE);

 Date date = parseDate(hour + ":" + minute);
 Date dateCompareOne = parseDate("08:00");
 Date dateCompareTwo = parseDate("20:00");

 if (dateCompareOne.before( date ) && dateCompareTwo.after(date)) {
    //your logic
 }

 private Date parseDate(String date) {

    final String inputFormat = "HH:mm";
    SimpleDateFormat inputParser = new SimpleDateFormat(inputFormat, Locale.US);
    try {
         return inputParser.parse(date);
    } catch (java.text.ParseException e) {
         return new Date(0);
    }
 }

此外,为了更加精确, 如果您比较的时间跨越了一天的00:00到24:00之间的区间, 那么您需要解析日期。


1
这是最好的和最稳健的回答之一。我建议每个人都试试这个方法。之前,我使用 Calendar 对象通过 after 和 before 方法来检查当前时间。结果令人困惑,有时正确,有时错误。例如:7:00 am 不晚于 7:00 am,但使用 calendar 对象时,它会给出 true 或 false 的状态。 - krisDrOid
这些糟糕的日期时间类已经被JSR 310的采用替代多年,使用* java.time *类。 - Basil Bourque

5

以下方法检查'validateTime'是否在'startTime'和'endTime'之间,同时考虑到'endTime'可能是第二天。为了正确使用它,请将您的日期解析为"HH:mm"格式。

 public static final boolean isBetweenValidTime(Date startTime, Date endTime, Date validateTime)
 {
        boolean validTimeFlag = false;

        if(endTime.compareTo(startTime) <= 0)
        {
            if(validateTime.compareTo(endTime) < 0 || validateTime.compareTo(startTime) >= 0)
            {
                 validTimeFlag = true;
            }
        }
        else if(validateTime.compareTo(endTime) < 0 && validateTime.compareTo(startTime) >= 0)
        {
             validTimeFlag = true;  
        }

        return validTimeFlag;
 }

4

阅读了几个回复之后,我感觉写作过于复杂。试试我的代码

 public static boolean compare(String system_time, String currentTime, String endtimes) {
    try {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");

        Date startime = simpleDateFormat.parse("19:25:00");
        Date endtime = simpleDateFormat.parse("20:30:00");

        //current time
        Date current_time = simpleDateFormat.parse("20:00:00");

    if (current_time.after(startime) && current_time.before(endtime)) {
            System.out.println("Yes");
            return true;
      }
    else if (current_time.after(startime) && current_time.after(endtime)) {
         return true; //overlap condition check
      }
     else {
            System.out.println("No");
            return false;
        }
    } catch (ParseException e) {
        e.printStackTrace();
    }
    return false;
 } 

您正在使用已经过时的麻烦老类,现在应该使用被java.time类替代的新类。 - Basil Bourque

3

Java 8 - LocalDateTime

这是什么?

final LocalDateTime now = LocalDateTime.now();
final LocalDateTime minRange = LocalDateTime.of(now.getYear(), now.getMonth(), now.getDayOfMonth(), 22, 30); //Today, 10:30pm
LocalDateTime maxRange = LocalDateTime.of(now.getYear(), now.getMonth(), now.getDayOfMonth(), 6, 30); //Tomorrow, 6:30am
maxRange = maxRange.plusDays(1); //Ensures that you don't run into an exception if minRange is the last day in the month.
if (now.isAfter(minRange) && now.isBefore(maxRange)) {
    //Action
}

这段代码涉及到日期,但问题只要求时间而不需要日期。 - Basil Bourque

3

使用LocalTime将简单忽略日期值:

public class TimeIntervalChecker {

static final LocalTime time1 = LocalTime.parse( "20:11:13"  ) ;
static final LocalTime time2 = LocalTime.parse( "14:49:00" ) ;

    public static void main(String[] args) throws java.lang.Exception {

        LocalTime nowUtcTime = LocalTime.now(Clock.systemUTC());

        if (nowUtcTime.isAfter(time1) && nowUtcTime.isBefore(time2)){
              System.out.println(nowUtcTime+" is after: "+ time1+" and before: "+ time2);
        } 

}

(a) 看起来很像我的答案。我没有看到任何增值。 (b) 不需要传递Clock.systemUTC(),因为当没有参数传递时,它是默认值。只需使用:Instant.now() - Basil Bourque
是的,也许看起来像你的代码,但如果我们只想检查给定时间是否在两个时间之间,而不考虑日期,那么它会更简洁明了。Clock.systemUTC() 用于使用当前日期的 UTC 时区,否则默认使用本地时区。 - kmarabet
1
关于需要传递时钟的观点,您是错误的。文档明确表示UTC是默认值,只有在使用虚假/更改后的时钟进行测试时才需要传递时钟。您将Instant.now与其他类的.now方法混淆了,如果省略,则确实会使用JVM的当前默认时区。 - Basil Bourque

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接