简体   繁体   中英

Lock underflow/overflow with Java LocalTime

When subtracting a given amount from a LocalTime object, I've realised that overflow/underflow can occur.

Example:

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

For my application, I would like lock times such that the above would generate 00:00 on underflow, and 23:59 on overflow.

Is this possible?

My suggestion is:

    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);

The above assumes that minutesToSubtract is non-negative. If negative numbers may occur, you need to check for both underflow and overflow.

The case of checking for overflow (more than 23:59:59.999999999 ) is similar. Use LocalTime.MAX for end of day.

Edit: JB Nizet's code for the other operation in his comment deserves proper code formatting, so I am pasting it here:

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));
}

In this example, a route should be locked x amount of time before it starts.

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;

On line 2 and 3, I am using % to avoid the lock time being greater than 24 hours. This way regardless of overflow/underflow, it can't pass the original time, so the checks on lines 6 and 7 will work.

I then assume that if the subtraction for earliest time is actually later than the stop, then it must have underflowed, therefore set it to 00:00, and the reverse for the latest time.

Finally, the times can be compared like so:

// 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.");
}

Whilst this solution is working for me right now, I would like to see if there are any other less verbose options. (Then again this is Java.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM