【问题标题】:LocalTime between 23.59 and 00:01 [closed]LocalTime 23.59 到 00:01 [关闭]
【发布时间】:2018-09-02 05:22:42
【问题描述】:

我想检查LocalTime 是否是午夜。对于这个用例,午夜被定义为介于23:5900:01 之间的任何时间。这是 2 分钟的范围。

private final LocalTime ONE_MINUTE_BEFORE_MIDNIGHT = LocalTime.of(23, 59, 0);
private final LocalTime ONE_MINUTE_AFTER_MIDNIGHT = LocalTime.of(0, 1, 0);

我有一个方法

public boolean isAtMidnight(LocalTime time) {
    return time.isAfter(ONE_MINUTE_BEFORE_MIDNIGHT)
        && time.isBefore(ONE_MINUTE_AFTER_MIDNIGHT);
}

此方法总是返回false。即使是LocalTime.MIDNIGHT。但是,它应该返回 true

如何检查时间是否距午夜 +-1 分钟?

【问题讨论】:

  • 提示:您确定要在 23:59 之后在 00:01 之前吗?
  • 建议:限制变量更明确地定义为private final LocalTime ONE_MINUTE_BEFORE_MIDNIGHT = LocalTime.MIDNIGHT.minusMinutes(1);,反之亦然
  • 当然,如果您想检查中午 +/- 1 分钟,您需要测试“11:59 之后 12:01 之前”。 ..
  • 出于好奇,为什么 23.59.01 被认为是午夜?

标签: java time java-8 java-time localtime


【解决方案1】:

解决办法是用||代替&&

public boolean isAtMidnight(LocalTime time) {
    return time.isAfter(ONE_MINUTE_BEFORE_MIDNIGHT) || time.isBefore(ONE_MINUTE_AFTER_MIDNIGHT);
}

这太违反直觉了,不是吗?诀窍是00:00:01 不在23:59 之后,所以这总是会失败。之所以如此,是因为 LocalTime.isAfterLocalTime.isBefore 假定这些时间是同一天

【讨论】:

  • 感谢您的解释
  • 这是一个比最高票数更好的答案。
  • @MrLister 我很不同意,主要是因为LocalTime 没有day 的概念。
【解决方案2】:

不要检查time是否在23:59之后00:01之前,你应该检查它是否在23:59之后00:01之前.

public boolean isAtMidnight(LocalTime time){
    return time.isAfter(ONE_MINUTE_BEFORE_MIDNIGHT) || time.isBefore(ONE_MINUTE_AFTER_MIDNIGHT);
}

如果我们查看LocalTime#isAfter 的实现,我们会看到以下内容:

public boolean isAfter(LocalTime other) {
    return compareTo(other) > 0;
}

看着LocalTime#compareTo

@Override
public int compareTo(LocalTime other) {
    int cmp = Integer.compare(hour, other.hour);
    if (cmp == 0) {
        cmp = Integer.compare(minute, other.minute);
        if (cmp == 0) {
            cmp = Integer.compare(second, other.second);
            if (cmp == 0) {
                cmp = Integer.compare(nano, other.nano);
            }
        }
    }
    return cmp;
}

我们可以看到LocalTime 的两个实例首先按各自的小时进行比较,然后是分钟,然后是秒,最后是纳秒。要使LocalTime#compareTo 返回大于0 的值以满足LocalTime#isAfter,第一个LocalTime 实例的小时数必须大于第二个实例的小时数。对于00:0023:59,这正确,因此您的方法返回false。可以对LocalTime#isBefore 进行相同的分析,您将得到相同的结果。

请记住,如果您想准确的话,可以只检查 LocalTime.MIDNIGHT,但我假设您正在考虑将 1 分钟范围内的任何时间都视为“午夜”(包括秒数)。

【讨论】:

    【解决方案3】:

    如果你真的需要这样做,它不能同时满足这两个陈述。考虑使用 or,此代码对我返回 true:

    public static void main(String[] args)
    {
        LocalTime ONE_MINUTE_BEFORE_MIDNIGHT = LocalTime.of(23, 59, 0);
        LocalTime ONE_MINUTE_AFTER_MIDNIGHT = LocalTime.of(0, 1, 0);
        LocalTime md = LocalTime.MIDNIGHT;
        System.out.println(md.isBefore(ONE_MINUTE_AFTER_MIDNIGHT) || md.isAfter(ONE_MINUTE_BEFORE_MIDNIGHT));
    }
    

    【讨论】:

      【解决方案4】:

      如前所述,您必须使用|| 而不是&&。如果您以这种方式重新组织条件中的变量,我认为更具可读性:

      public boolean isAtMidnight(LocalTime time) {
          return ONE_MINUTE_BEFORE_MIDNIGHT.isBefore(time) || ONE_MINUTE_AFTER_MIDNIGHT.isAfter(time);
      }
      

      一分钟之前午夜是之前...

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-14
        • 1970-01-01
        • 2011-05-07
        • 1970-01-01
        • 2021-06-11
        • 1970-01-01
        相关资源
        最近更新 更多