Using the Java Instant class, how can I round up to the nearest second? I don't care if it is 1 millisecond, 15 milliseconds, or 999 milliseconds, all should round up to the next second with 0 milliseconds.
I basically want,
Instant myInstant = ...
myInstant.truncatedTo(ChronoUnit.SECONDS);
but in the opposite direction.
You can cover the corner case by using .getNano
to make sure the time is not exactly even on the second and then add the extra second using .plusSeconds()
when there is a value to truncate.
Instant myInstant = Instant.now();
if (myInstant.getNano() > 0) //Checks for any nanoseconds for the current second (this will almost always be true)
{
myInstant = myInstant.truncatedTo(ChronoUnit.SECONDS).plusSeconds(1);
}
/* else //Rare case where nanoseconds are exactly 0
{
myInstant = myInstant;
} */
I left in the else
statement just to demonstrate no operations need to be done if it is exactly 0 nanoseconds, because there is no reason to truncate nothing.
EDIT: If you want to check if the time is at least 1 millisecond over a second in order to round up, instead of 1 nanosecond you can then compare it to 1000000 nanoseconds but leave the else
statement in to truncate the nanoseconds:
Instant myInstant = Instant.now();
if (myInstant.getNano() > 1000000) //Nano to milliseconds
{
myInstant = myInstant.truncatedTo(ChronoUnit.SECONDS).plusSeconds(1);
}
else
{
myInstant = myInstant.truncatedTo(ChronoUnit.SECONDS); //Must truncate the nanoseconds off since we are comparing to milliseconds now.
}
You can use the lambda functional programming streams approach to make this a one liner.
Add a second and truncate. To cover the corner case of being exactly on a second, check the truncated to the original, and only add a second if they differ:
Instant myRoundedUpInstant = Optional.of(myInstant.truncatedTo(ChronoUnit.SECONDS))
.filter(myInstant::equals)
.orElse(myInstant.truncatedTo(ChronoUnit.SECONDS).plusSeconds(1));
See this code run line at IdeOne.com.
Instant.toString(): 2019-07-30T20:06:33.456424Z
myRoundedUpInstant(): 2019-07-30T20:06:34Z
…and…
myInstant.toString(): 2019-07-30T20:05:20Z
myRoundedUpInstant(): 2019-07-30T20:05:20Z
Or alternatively, with a slightly different approach:
Instant myRoundedUpInstant = Optional.of(myInstant)
.filter(t -> t.getNano() != 0)
.map(t -> t.truncatedTo(ChronoUnit.SECONDS).plusSeconds(1))
.orElse(myInstant);
See this code run live at IdeOne.com.
myInstant.toString(): 2019-07-30T20:09:07.415043Z
myRoundedUpInstant(): 2019-07-30T20:09:08Z
…and…
myInstant.toString(): 2019-07-30T19:44:06Z
myRoundedUpInstant(): 2019-07-30T19:44:06Z
Above is of course in Java 8 land. I'll leave it as an exercise to the reader to split that out into the more traditional if/else if Optional
isn't your thing :-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With