kotlinx-datetime icon indicating copy to clipboard operation
kotlinx-datetime copied to clipboard

Previous/next date and/or time with the given form

Open dkhalanskyjb opened this issue 2 years ago • 12 comments

"I have a date or a time, and I want to round/adjust it."

Examples:

  • Find the last time it was Monday (or Sunday) not later than the given date: https://github.com/Kotlin/kotlinx-datetime/issues/129#issuecomment-1152301045
  • Given the local time, find the 1-hour slot it matches (13:45:12.513 -> 13:00:00.000): https://github.com/Kotlin/kotlinx-datetime/issues/223#issuecomment-1484976078
  • Discard the sub-minute components when formatting a Duration: https://github.com/Kotlin/kotlinx-datetime/issues/225#issuecomment-1240884960 (can also be solved by tweaking the formatter).
  • Find the next time a given day of the week happens: https://github.com/Kotlin/kotlinx-datetime/issues/235#issuecomment-1336388102
  • Internally, we need functions like "find the last Sunday in the given month" to calculate the moments when timezone transitions happen.

dkhalanskyjb avatar Dec 01 '23 13:12 dkhalanskyjb

One practical use case for such functionality: the OCPP specification. It mandates that ISO date/time strings don't have more than 3 decimal points:

number of decimal places SHALL NOT exceed the maximum of 3.

In other words: no more than millisecond precision.

While working with kotlinx-datetime, we actually ran into compatibility problems with vendors that will flat out reject the nanosecond-precise ISO date/time strings that kotlinx.datetime.Instant gets serialized to by kotlinx.serialization.

We could use JSR-310 (java.time) instead, so we could solve it with truncateTo, or we can write a helper function as suggested on StackOverflow, but I was kind of hoping that there would be an equally convenient built-in multiplatform solution for this.

volkert-fastned avatar Feb 22 '24 16:02 volkert-fastned

Update:

I found a single-line workaround for forcibly reducing the precision to millisecond-level in serialized ISO date/time strings, at least for timestamps originating from the system clock:

import kotlinx.datetime.Clock
import kotlinx.datetime.Instant

// Will have 6 digits behind the decimal point on Kotlin/JVM, but 3 digits on Kotlin/JS and Kotlin/Native
println(Clock.System.now())

// Will have 3 digits behind the decimal point on Kotlin/JVM, Kotlin/JS and Kotlin/Native
println(Instant.fromEpochMilliseconds(Clock.System.now().toEpochMilliseconds()))

So Kotlin/JVM appears to appears to be the only Kotlin platform that creates Instants from the system clock at nanosecond precision, although I haven't tried it with Kotlin for Android yet.

volkert-fastned avatar Feb 22 '24 19:02 volkert-fastned

@volkert-fastned, since your problem is with system interoperability, the upcoming API for parsing and formatting may solve it: https://github.com/Kotlin/kotlinx-datetime/pull/343

dkhalanskyjb avatar Feb 23 '24 07:02 dkhalanskyjb