Dominik Sandjaja
06/09/2023, 8:25 AMtimestamp
column.
PostgreSQL has microsecond resolution for that column.
On MacOS, this works because Clock.System.now()
also returns an Instant
with microsecond resolution, so comparing an object before persisting it and after retrieving it from the database works.
On Linux (which we use for our pipeline) this same comparison fails because 2023-06-09T07:34:27.965341799Z != 2023-06-09T07:34:27.965342Z
I found similar issues for e.g. H2, but there it seems possible to simply store nanoseconds in the database.
It is not necessarily an issue to change the tests, we can simply set fixed instants (without nanosecond precision), but the question remains nevertheless:
Is there a way to force Kotlin to always use a specific precision?Dominik Sandjaja
06/09/2023, 8:26 AMDmitry Khalanskiy [JB]
06/09/2023, 8:47 AMDominik Sandjaja
06/09/2023, 8:49 AMJeff Lockhart
06/10/2023, 6:37 PMfun Clock.nowMillis() = Instant.fromEpochMilliseconds(now().toEpochMilliseconds())
Michael Strasser
06/13/2023, 12:33 AMInstant
does not have a truncatedTo()
function, like java.time.Instant
. I have used that in JVM projects that needed to behave the same on macOS and Linux.
I try to ensure better than millisecond precision in most cases, because even basic desktop machines run faster than that these days.Michael Strasser
06/13/2023, 12:35 AMDmitry Khalanskiy [JB]
06/13/2023, 7:34 AMInstant.truncateTo
is the answer.
The bottom line: if someone thinks the functionality is worth having, they will have to spell it out for us with clear examples of why it would be useful.Michael Strasser
06/13/2023, 7:45 AMtruncatedTo()
function. I think aligning values between systems of different precisions might be. When I used it on the JVM I had tests that passed on Mac but failed on Linux because the JVM uses the system clock, which has microsecond precision on macOS and nanosecond precision on Linux.
If I want that in kotlinx-datetime I will probably write an extension function first.Dmitry Khalanskiy [JB]
06/13/2023, 11:16 AMtruncateTo
in a way similar to this:
val instant1 = Clock.System.now()
val instant2 = sendToServerAndReceiveBack(instant1)
assertEquals(instant1.toEpochMilliseconds(), instant2.toEpochMilliseconds())
I think this reflects the intention even better than
val instant1 = Clock.System.now().roundTo(DateTimeUnit.MILLISECOND)
val instant2 = sendToServerAndReceiveBack(instant1)
assertEquals(instant1, instant2)
After all, the second operation potentially loses precision, and we want to check precisely that the millisecond portion is always preserved, not that this operation preserves an Instant
as long as it's rounded to lose precision.Dmitry Khalanskiy [JB]
06/13/2023, 11:19 AMKlitos Kyriacou
06/13/2023, 11:27 AMDominik Sandjaja
06/13/2023, 12:47 PM.truncate(...)
method or the alternative .with(...)
sounds like a good idea. I would then put it into the set()
or get()
part of the class which has Instant
fields, making sure to always have a certain precision. For now that should also be possible by converting the provided Instant
from Clock.now()
, e.g. via Clock.System.now()._toJavaInstant_().with(ChronoField._NANO_OF_SECOND_, 0L)._toKotlinInstant_()
Klitos Kyriacou
06/13/2023, 1:01 PMtruncateTo
might be useful, but Java's version of truncateTo
is limited to truncating to single units. What if you wanted the time to the nearest quarter of an hour? Perhaps that could be done with a round(Duration, RoundingMode)
which allows you to round down, up, half up etc. But that sounds too specialized and can be user-created per application.