营业时间判断?

营业时间: 13:00 - 次日03:00 如我输入一个16:34 或 03:10 判断是否在这个区间?

回复
阅读 3.1k
5 个回答

单从同一天的24小时来判断的,肯定是

startTime < validateTime < endTime

但题主的需求是"13:00 - 次日03:00",也就不是同一天,是跨天的, 如果还是从24小时的判断来说:

endTime < startTime

所以此时的逻辑反而变成

validateTime < endTime || validateTime > startTime

LocalTime写成代码应该就类似如下:

LocalTime startTime = LocalTime.of(13, 0);
LocalTime endTime = LocalTime.of(3, 0);
LocalTime validateTime1 = LocalTime.of(16, 34);
LocalTime validateTime2 = LocalTime.of(3, 10);

Predicate<LocalTime> endBeforeStartPredicate = localTime -> localTime.isAfter(startTime) || localTime.isBefore(endTime);

System.out.println(endBeforeStartPredicate.test(validateTime1)); // true
System.out.println(endBeforeStartPredicate.test(validateTime2)); // false

如果考虑更加通用的方式,也就是startTimeendTime也是变量,即不考虑是否到底是同一天相比还是跨天相比。

那这个Predicate<LocalTime>就需要变为BiFunction<LocalTime, LocalTime, Predicate<LocalTime>>

LocalTime startTime = LocalTime.of(13, 0);
LocalTime endTime = LocalTime.of(3, 0);
LocalTime validateTime1 = LocalTime.of(16, 34);
LocalTime validateTime2 = LocalTime.of(3, 10);

BiFunction<LocalTime, LocalTime, Predicate<LocalTime>> biFunction = (start, end) ->
                end.isAfter(start)
                        ? localTime -> localTime.isAfter(start) && localTime.isBefore(end)
                        : localTime -> localTime.isAfter(start) || localTime.isBefore(end);


System.out.println(biFunction.apply(startTime, endTime).test(validateTime1)); // true
System.out.println(biFunction.apply(startTime, endTime).test(validateTime2)); // false

// startTime和endTime换一下位置,此时表示是当天的时间的比较,没有跨天
System.out.println(biFunction.apply(endTime, startTime).test(validateTime1)); // false
System.out.println(biFunction.apply(endTime, startTime).test(validateTime2)); // true

biFunction这里的写法比较捡懒同时可以让代码放在一起,你可以选择整一个工具方法放着都行,感觉这样差不多叭~( ̄(エ) ̄)

这个时间区间映射到一天后其实是2个闭区间
[0:00,3:00][13:00,24:00],这样不方便比较,其实再取一次反,表明不在营业时间的是(3:00,13:00)
所以对待判断时间aTime的判断就可以是
!(3:00<aTime<13:00)

如果判断的时间区间在 24 小时内,可以引入一个偏移量来处理。

比如这个区间是在 [13:00, 3:00),那么用 13 小时来作为偏移量(区间起的小时数),可以写个函数

// 是按前才后开区间来判断的
static boolean inRange(LocalTime current, LocalTime begin, LocalTime end) {
    var offset = begin.getHour();       // 用开始时间来找偏移量
    var b = begin.minusHours(offset);   // 三个时间都减去偏移量
    var e = end.minusHours(offset);
    var v = current.minusHours(offset);
    return !b.isAfter(v) && e.isAfter(v);
}

完整的测试代码

import java.time.LocalTime;

public class Problem {
    public static void main(String[] args) {
        var beginTime = LocalTime.of(13, 0);
        var endTime = LocalTime.of(3, 0);
        var v1 = LocalTime.of(16, 34);
        var v2 = LocalTime.of(3, 10);
        System.out.println("v1: " + inRange(v1, beginTime, endTime));  // true
        System.out.println("v2: " + inRange(v2, beginTime, endTime));  // false
    }

    private static boolean inRange(LocalTime current, LocalTime begin, LocalTime end) {
        var offset = begin.getHour();
        var b = begin.minusHours(offset);
        var e = end.minusHours(offset);
        var v = current.minusHours(offset);
        return !b.isAfter(v) && e.isAfter(v);
    }
}

如果区间大于 24 小时,那就必须要引入“天”的概念了,可以找一个基础时间来算每个时间的偏移时间差(根据精度,一般可以以秒为单位)。

把字符串转换成时间,new Date("YYYY-DD-MM HH:mm:ss")
然后用大于小于比较

假设今天0点时间为0,一个小时是1000 * 60 * 60 = 3,600,000毫秒
那今日13点为 A = 3,600,000 *13
次日03:00为 C = 3,600,000 * 27;

所有你把16:34解析成精确到毫秒的时间B 只需要判断 A<=B<=C

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏