Home > Blockchain >  Round instant with more than 6 digits (nanoseconds) after comma
Round instant with more than 6 digits (nanoseconds) after comma

Time:10-17

I have postgresql with TIMESTAMP field, which have Instant with date and time. For example: 2021-10-13T15:04:24.944921Z.

As you can see, there are 6 digits after comma - 944921. But what if I have more digits, for example: 2021-10-13T07:14:47.791616921Z. How can I correctly round such Instant to 2021-10-13T07:14:47.791617Z?

CodePudding user response:

The code is short but requires a bit of explanation. You are right, the best we have is the truncatedTo method, and it always rounds down. Instead we want the half-up rounding that we learned in school: If the 7th decimal is 4 or less, round down. If it is 5 or higher, round up.

To obtain this I first add 500 nanoseconds. Then truncate. If the 7th decimal was 4 or less, it is still 9 or less, so the digits before it have not been changed, and truncation will do the rounding-down that we want. If the 7th decimal was 5 or more, adding 500 nanoseconds will overflow it, the 6th decimal will be incremented by 1, and the 7th decimal will end up in the 0 through 4 range. Then truncation will effectively do the rounding up of the original value that we wanted.

    Instant sourceValue = Instant.parse("2021-10-13T07:14:47.791616921Z");
    Instant rounded = sourceValue.plusNanos(500).truncatedTo(ChronoUnit.MICROS);
    System.out.println(rounded);

Output is the desired:

2021-10-13T07:14:47.791617Z

Let’s try the edge cases too.

    Instant sourceValue = Instant.parse("2021-10-13T07:14:00.000000499Z");

2021-10-13T07:14:00Z

    Instant sourceValue = Instant.parse("2021-10-13T07:14:59.999999500Z");

2021-10-13T07:15:00Z

  • Related