Lock underflow/overflow with Java LocalTime

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP



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.


00:00


23:59



Is this possible?





Why wouldn't it be possible? Try writing the code, and ask us if you have a concrete problem, posting the code you wrote.
– JB Nizet
Aug 12 at 12:51






can show us an example about overflow
– YCF_L
Aug 12 at 12:51


overflow





@JBNizet I'll post the solution I'm using, but I was just curious what solutions existed.
– Jordan Mackie
Aug 12 at 12:52





@Pshemo Yep. My bad.
– Jordan Mackie
Aug 12 at 13:01




2 Answers
2



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.


minutesToSubtract



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


23:59:59.999999999


LocalTime.MAX



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





I would use the same idea. Here's my implementation for the other operation: 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));
– JB Nizet
Aug 12 at 13:10


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






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Firebase Auth - with Email and Password - Check user already registered

Dynamically update html content plain JS

How to determine optimal route across keyboard