Home > database >  Inline formatting LocalTime.now() in Kotlin
Inline formatting LocalTime.now() in Kotlin

Time:08-29

I'm trying to figure out how to inline format my LocalTime variable if it's default. This is what I currently have:

...
var timeOutgoing: LocalTime = LocalTime.now().plusHours(1)
...

The result when I create the object could be for example 15:05:22.2463181 when I'm only looking for 15:05

When I try to do the following:

var timeOutgoing: LocalTime = LocalTime.now().plusHours(1).format(DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT))

It then complains with a Type Missmatch stating I should use a String? instead of LocalTime.

How do I go about inline formatting it to match, for example: 15:02?

Cheers

CodePudding user response:

You need to parse string to get LocalTime like this.

   var timeOutgoing: LocalTime = LocalTime.parse(LocalTime.now().plusHours(1).format(DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT)),DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT))

Also you can make it as reusable extension function like below:

   fun LocalTime.formatTime(formatStyle: FormatStyle= FormatStyle.SHORT): LocalTime = LocalTime.parse(this.format(DateTimeFormatter.ofLocalizedTime(formatStyle)),DateTimeFormatter.ofLocalizedTime(formatStyle))

Usage:

var timeOutgoing: LocalTime = LocalTime.now().plusHours(1).formatTime(FormatStyle.SHORT)

(or)

 var timeOutgoing: LocalTime = LocalTime.now().plusHours(1).formatTime()

As formatTime has default value as FormatStyle.SHORT

CodePudding user response:

A LocalTime does not have a format, "inline" or otherwise. It is simply data representing a time with no date nor timezone. It's when you convert a temporal object to a String, or vice versa, that you use a "format". That format is specified by the DateTimeFormatter, not by the temporal object.

That said, temporal classes such as LocalTime do implement toString(), and so they have to use a default format. Here is the documentation of LocalTime#toString():

Outputs this time as a String, such as 10:15.

The output will be one of the following ISO-8601 formats:

  • HH:mm
  • HH:mm:ss
  • HH:mm:ss.SSS
  • HH:mm:ss.SSSSSS
  • HH:mm:ss.SSSSSSSSS

The format used will be the shortest that outputs the full value of the time where the omitted parts are implied to be zero.

- See DateTimeFormatter to understand what those formats mean.

That means when the seconds and nanoseconds are zero then LocalTime#toString() will use the HH:mm pattern. You can zero-out those fields with the truncatedTo(ChronoUnit) method. So, this approach seems closest to your desire to have some sort of "inline format", as it does not involve using a custom DateTimeFormatter.

Here's an example demonstrating the above information:

import java.time.LocalTime
import java.time.format.DateTimeFormatter
import java.time.temporal.ChronoUnit

fun main() {
    val time = LocalTime.of(12, 30, 45, 987_654_321);
    val truncatedTime = time.truncatedTo(ChronoUnit.MINUTES)
    val formatter = DateTimeFormatter.ofPattern("HH:mm");

    println("time.toString()          -> $time")
    println("time.format('HH:mm')     -> ${time.format(formatter)}")
    println("truncatedTime.toString() -> $truncatedTime")
}

Output:

time.toString()          -> 12:30:45.987654321
time.format('HH:mm')     -> 12:30
truncatedTime.toString() -> 12:30

Where you apply the solution depends on how exactly the code you've provided is used. For instance, maybe all you need to do is:

var timeOutgoing: LocalTime = LocalTime.now().plusHours(1).truncatedTo(ChronoUnit.MINUTES)

But since you've tagged this question with , perhaps this code is part of e.g., an HTTP response, and so it may make more sense to format the time when converting the data object to e.g., JSON.

  • Related