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

Provide custom formats for `DateTimePeriod`

Open dkhalanskyjb opened this issue 1 year ago • 5 comments

Currently, DateTimePeriod supports toString and parse using the ISO 8601 format. With the recent introduction of the parsing and formatting machinery, we can add support for arbitrary formats.

dkhalanskyjb avatar Feb 29 '24 12:02 dkhalanskyjb

kotlinx.datetime.format.DateTimeFormat implementations should be public to enable custom formats to be created.

jfontsaballs avatar Oct 30 '24 09:10 jfontsaballs

@jfontsaballs, please provide an example of what you can't currently express with the API we provide. What if it's already possible?

dkhalanskyjb avatar Oct 30 '24 09:10 dkhalanskyjb

I need to parse data received from a third party that does not conform to ISO standards.

LocalTime.parse("9:16")

Throws:

kotlinx.datetime.DateTimeFormatException: java.time.format.DateTimeParseException: Text '9:16' could not be parsed at index 0
	at kotlinx.datetime.LocalTime$Companion.parse(LocalTime.kt:53)
	at kotlinx.datetime.LocalTime$Companion.parse$default(LocalTime.kt:48)
	at Line_3.<init>(Line_3.kts:3)
Caused by: java.time.format.DateTimeParseException: Text '9:16' could not be parsed at index 0
	at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2052)
	at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1954)
	at java.base/java.time.LocalTime.parse(LocalTime.java:465)
	at java.base/java.time.LocalTime.parse(LocalTime.java:450)
	at kotlinx.datetime.LocalTime$Companion.parse(LocalTime.kt:51)

Currently I'm using the Java API:

import java.time.LocalTime
import java.time.format.DateTimeFormatterBuilder
import java.time.temporal.ChronoField

private val formatter = DateTimeFormatterBuilder()
  .appendValue(ChronoField.HOUR_OF_DAY)
  .appendLiteral(':')
  .appendValue(ChronoField.MINUTE_OF_HOUR)
  .toFormatter()
val JsonElement.localTime get() = LocalTime.parse(this.string, formatter).toKotlinLocalTime()

I would like to write the following code but those APIs are internal.

    LocalTimeFormat.build {
        hour(Padding.NONE)
        char(':')
        minute(Padding.NONE)
    }

jfontsaballs avatar Oct 30 '24 09:10 jfontsaballs

@jfontsaballs, it's available from a different entry point:

import kotlinx.datetime.*
import kotlinx.datetime.format.*

fun main() {
    val format = LocalTime.Format {
        hour(Padding.NONE)
        char(':')
        minute(Padding.NONE)
    }
    println("The time is ${format.parse("9:16")}")
}

Runnable: https://pl.kotl.in/znkv3rbiZ

Please also take a look at https://github.com/Kotlin/kotlinx-datetime?tab=readme-ov-file#working-with-other-string-formats

dkhalanskyjb avatar Oct 30 '24 10:10 dkhalanskyjb

Great, thank you!

I'd like to request kotlinx.datetime.format.ISO_TIME (and other similar constants) be changed to use the public API, in order to improve discoverability of it when inspecting the code without having read the documentation.

jfontsaballs avatar Oct 30 '24 10:10 jfontsaballs