【问题标题】:Time within a particular time interval特定时间间隔内的时间
【发布时间】:2010-07-21 09:23:28
【问题描述】:

我正在尝试解决一个看似简单的问题,但我无法完全理解它。

我有两次startTimestopTime,可以认为是格式:hh:mm:ss[24小时格式]。

现在给出第三次 - timeToTest - 我需要找出 timeToTest 是否介于 startTimestopTime 之间。除了时间之外,不涉及日期信息。

例如 - 如果我有 startTime = '22:30:00'stopTime = '03:30:00',那么对于 timeToTest = '01:14:23',测试应该返回 true。

我已尝试使用java.util.Date 的解决方案,通过使用getTime() 将时间转换为毫秒,但任何超过24 小时障碍的时间间隔,逻辑都会失败。

我正在尝试使用 Java 构建解决方案 - 但我相信逻辑与语言无关。

【问题讨论】:

    标签: java date time


    【解决方案1】:

    所以我能想出的最简单的解决方案,坚持简单的旧java.util.Date,如下所示:

        String d1 = "21:00:00";
        String d2 = "04:00:00";
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
        String dToTest = "16:00:00";
        boolean isSplit = false, isWithin = false;
    
        Date dt1 = null, dt2 = null,  dt3 = null;
    
        dt1 = sdf.parse(d1);
        dt2 = sdf.parse(d2);
        dt3 = sdf.parse(dToTest);
    
        isSplit = (dt2.compareTo(dt1) < 0);
        System.out.println("[split]: " +isSplit);
    
        if (isSplit)
        {
            isWithin = (dt3.after(dt1) || dt3.before(dt2));
        }
        else
        {
            isWithin = (dt3.after(dt1) && dt3.before(dt2));
        }
    
        System.out.println("Is time within interval? " +isWithin);
    

    请随时指出任何错误 - 愿意工作并修复它。

    【讨论】:

      【解决方案2】:

      您必须添加一个“天”,其中“0”== 当天,“1”== 第二天,依此类推。所以实际上stopTime == '03:30:00' 应该是'27:30:00'(即第二天)。

      在您的情况下,如果stopTime &lt; startTime,则添加 86400 秒。

      【讨论】:

      • aaron,我试过在stopTime 小于startTime 时添加一天的方法。然而,我面临的问题是——我什么时候决定在timeToTest 中增加一天。例如,我应该给timeToTest 添加一天> 00:00:00 但stopTime。但是当它是 00:00:00 我不应该。此外,由于我需要在数据集上运行此逻辑,我不知何故觉得进行如此多的检查并创建新的 Date 对象可能会导致性能开销。
      • 嗯,如果时间是在午夜之后,那么就是第二天。您的问题是“日”信息被丢弃了,并且没有安全的方法可以从剩下的部分重新创建它。唯一安全的解决方案是在创建数据时保留这一重要事实。
      • 提到性能:当您的解决方案工作并且很慢时开始担心它。避免过早优化。
      【解决方案3】:

      anirvan 使用 JodaTime 的解决方案:

      public class TimeInterval24H {
          private final LocalTime start;
          private final LocalTime end;
      
          public TimeInterval24H(LocalTime start, LocalTime end) {
              this.start = start;
              this.end = end;
          }
      
          public TimeInterval24H(Date start, Date end) {
              this(new LocalTime(start), new LocalTime(end));
          }
      
          public boolean contains(Date test) {
              return contains(new LocalTime(test));
          }
      
          public boolean contains(LocalTime test) {
              if (isAccrossTwoDays()) {
                  return (test.isAfter(getStart()) || test.isBefore(getEnd()));
              } else {
                  return (test.isAfter(getStart()) && test.isBefore(getEnd()));
              }
          }
      
          boolean isAccrossTwoDays() {
              return getEnd().isBefore(getStart());
          }
      
          public LocalTime getStart() {
              return start;
          }
      
          public LocalTime getEnd() {
              return end;
          }
      
      }
      

      【讨论】:

        【解决方案4】:

        java.time

        java.util 日期时间 API 及其格式化 API SimpleDateFormat 已过时且容易出错。建议完全停止使用,改用modern Date-Time API*

        另外,下面引用的是来自home page of Joda-Time的通知:

        请注意,从 Java SE 8 开始,用户被要求迁移到 java.time (JSR-310) - JDK 的核心部分,它取代了这个项目。

        使用现代日期时间 API java.time 的解决方案:

        import java.time.LocalDate;
        import java.time.LocalDateTime;
        import java.time.LocalTime;
        
        public class Main {
            public static void main(String[] args) {
                String strStartTime = "22:30:00", strStopTime = "03:30:00", strTestTime = "01:14:23";
                LocalDate today = LocalDate.now();
        
                LocalDateTime startTime = today.atTime(LocalTime.parse(strStartTime));
        
                LocalDateTime stopTime = today.atTime(LocalTime.parse(strStopTime));
                if (stopTime.isBefore(startTime))
                    stopTime = stopTime.plusDays(1);
        
                LocalDateTime testTime = today.atTime(LocalTime.parse(strTestTime));
                if (testTime.isBefore(startTime))
                    testTime = testTime.plusDays(1);
        
                if (!testTime.isBefore(startTime) && !testTime.isAfter(stopTime))
                    System.out.println(strTestTime + " is at or after " + strStartTime + " and is before or at " + strStopTime);
            }
        }
        

        输出:

        01:14:23 is at or after 22:30:00 and is before or at 03:30:00
        

        ONLINE DEMO

        注意:如果不包括开始时间和停止时间,则将条件更改如下:

        if (testTime.isAfter(startTime) && testTime.isBefore(stopTime))
            System.out.println(strTestTime + " is after " + strStartTime + " and is before " + strStopTime);
        

        Trail: Date Time 了解有关现代日期时间 API 的更多信息。


        * 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 和 7 . 如果您正在为一个 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

        【讨论】:

          【解决方案5】:

          怎么样:

          • 查找开始时刻之后指定时间的下一次出现
          • 检查该事件是否在结束时刻之前

          第一步可能很容易分解:

          • 指定的时间是否在开始瞬间的时间之后/之后?
            • 是的:下一次出现是与开始时刻同一天的那个时间
            • 否:下一次出现是从开始时刻开始的下一个天的那个时间

          顺便说一句,在Joda Time 中编写所有这些可能比使用 java.util.* 更容易:)

          【讨论】:

          • 确实,Joda Time 非常好,也许新的 JSR-310 jsr-310.dev.java.net 实现将解决 java.util.Date 的许多丑陋问题。
          • jon,这也是我一直在研究的逻辑。但是,诸如查找指定时间的下一次出现之类的事情是我发现很难或相当复杂地弄清楚 [使用 java.util.Date]。我正在研究 Joda,但还没有看到可以简化该任务的东西。
          • @anirvan:Joda Time 可以轻松区分“LocalDateTime”、“LocalDate”和“LocalTime”的概念。如果您使用完整的 DateTime 值,事情会变得混乱,其中可能涉及 DST 更改......例如,有时您可能会从晚上 10 点开始,到第二天下午 5 点结束 - 但两者之间没有上午 1.30 ...
          【解决方案6】:

          我强烈推荐 java.util.Calendar,before() 和 after() 很有用。但是,您需要指定一个日期,例如 2011 年 5 月 18 日以及您的时间。是否可以指定一个模拟日期(或您的情况下的一对日期)来利用日历?

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-11-18
            • 2018-02-20
            相关资源
            最近更新 更多