使用 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));
}
当从 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));
}