使用 Java LocalTime 锁定 underflow/overflow

Lock underflow/overflow with Java LocalTime

当从 LocalTime 对象中减去给定的数量时,我意识到 overflow/underflow 可能会发生。

示例:

00:30 - 35 minutes = 23:55
23:30 + 35 minutes = 00:05

对于我的应用程序,我希望锁定时间使得上述内容在下溢时生成 00:00,在溢出时生成 23:59

这可能吗?

在此示例中,路线应在开始前锁定 x 时间。

1 |LocalTime firstStopTime = firstStop.getStopTime(); 
2 |LocalTime earliestTime = firstStopTime.minus(beforeRouteLockTimeMins % 1440, ChronoUnit.MINUTES);
3 |LocalTime latestTime = firstStopTime.plus(afterRouteTimeLockMins % 1440, ChronoUnit.MINUTES);
4 |
5 |// Handle underflow/overflow when getting earliest/latest time
6 |if (earliestTime.isAfter(firstStopTime)) earliestTime = LocalTime.MIN;
7 |if (latestTime.isBefore(firstStopTime)) latestTime = LocalTime.MAX;

在第 2 行和第 3 行,我使用 % 来避免锁定时间超过 24 小时。这样不管overflow/underflow,都过不了原来的时间,所以第6行和第7行的检查就可以了

然后我假设如果最早的减法实际上晚于停止,那么它一定是下溢,因此设置为00:00,最晚的则相反。

最后,时间可以这样比较:

// Check route is within time constraint
if (currentTime.isBefore(earliestTime)) {
    return new RouteAvailabilityResponseModel(false, "Too early to begin route.");
} else if (currentTime.isAfter(latestTime)) {
    return new RouteAvailabilityResponseModel(false, "Too late to begin route.");
} else {
    return new RouteAvailabilityResponseModel(true, "Route can be started.");
}

虽然此解决方案目前对我有效,但我想看看是否还有其他更简洁的选项。 (然后又是Java。)

我的建议是:

    LocalTime orig = LocalTime.of(0, 30);
    int minutesToSubtract = 35;
    long minutesSinceMidnight = ChronoUnit.MINUTES.between(LocalTime.MIN, orig);
    LocalTime result;
    if (minutesToSubtract > minutesSinceMidnight) {
        // Subtracting the minutes will pass midnight at start of day
        result = LocalTime.MIN;
    } else {
        // Normal case, no underflow
        result = orig.minusMinutes(minutesToSubtract);
    }
    System.out.println(result);

上面假设minutesToSubtract是非负的。如果可能出现负数,需要同时检查下溢和上溢

检查溢出的情况(大于23:59:59.999999999)类似。使用 LocalTime.MAX 作为一天的结束。

编辑: JB Nizet 评论中其他操作的代码需要正确的代码格式,所以我将其粘贴在这里:

public static LocalTime addWithoutOverflow(LocalTime baseTime, int minutes) {
    LocalTime maxTime = LocalTime.MAX;
    long maxNanos = ChronoUnit.NANOS.between(baseTime, maxTime);
    long nanos = Duration.ofMinutes(minutes).toNanos();
    return baseTime.plusNanos(Math.min(maxNanos, nanos));
}