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 spring-boot, 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.