Kotlin / kotlinx-datetime

KotlinX multiplatform date/time library
Apache License 2.0
2.32k stars 93 forks source link

Consider adding parsing and formatting support for `kotlin.time.Duration` #348

Open dkhalanskyjb opened 4 months ago

dkhalanskyjb commented 4 months ago

Even though it's not strictly part of this library, it could still benefit from DateTimeFormat formatting capabilities. Please share your use cases and suggestions here.

mgroth0 commented 3 weeks ago

I would like this. I display durations in console output, reports, and compose GUIs often in similar places to where I display dates, so it would be nice to have similar formatting options. I also could use this to make a custom parser for a duration input component in compose.

dkhalanskyjb commented 2 weeks ago

@mgroth0, thanks! Could you share some examples of the Duration formats that you need?

mgroth0 commented 2 weeks ago

Sure!

One example is for a stopwatch component, which displays the time an operation has been running. The string is guaranteed to be N characters long (I have N at 18).

  1. I disallow negative durations
  2. For zero, I return "0".padStart(N)
  3. Next, I dermine the largest unit in which the value is at least 1
  4. Based on the largest unit, I branch out into different logics
    • MICROSECONDS: "${inWholeMicroseconds}µs".padStart(N)
    • MILLISECONDS: "${inWholeMilliseconds}ms.padStart(N)"
    • SECONDS: "${toDouble(SECONDS).toStringRoundedToDecimalWithPaddedZeros(3)}.padStart(N)"
    • MINUTES: "${minutesPart.toString().padStart(2)}m ${secondsPart.toString().padStart(2)}s ${ millisecondsPart.toString().padStart(3) }ms".padStart(N)
    • HOURS: "${minutesPart.toString().padStart(2)}m ${secondsPart.toString().padStart(2)}s ${ millisecondsPart.toString().padStart(3) }ms".padStart(N)

It works but it also feels a little messy and I'm not sure if this is the best approach. One nice thing about having the library have first class support for this sort of thing is it helps me figure out the best way to do it.

And that would only work for formatting an existing value. Parsing would be a whole different animal and I guess it might not work with this sort of format.

mgroth0 commented 2 weeks ago

Another format I have is very similar, but is designed for text to speech so it uses the full unit names instead of the abbreviations, and doesn't care about padding.

The other feature I have in mind is one that I haven't developed yet, but it would allow users to type an arbitrary duration into a text field and it would be parsed into a Duration value.

dkhalanskyjb commented 2 weeks ago

Hm. I don't think that DateTimeFormat-style formats provided by this library are a good fit for your use case: even if we do provide an API to support the conditionals of this form, I'm not sure that the resulting code will look more concise/readable than building strings by hand.

What your code could certainly benefit from is some way to conveniently format numbers, so ${minutesPart.toString().padStart(2)} would become something like ${minutesPart:02}.