kotlinjava-timedatetimeformatter

How to make LocalDateTime.parse reject 24:00 time


I have a form where user can input date and time from keypad and LocalDateTime accepts input when time part of input is 24:00, converting it to next day.

My code

import java.time.LocalDateTime
import java.time.format.DateTimeFormatter

val INPUT_DATETIME_PATTERN = "yyyyMMddHHmm"
val formatter = DateTimeFormatter.ofPattern(INPUT_DATETIME_PATTERN)
    
val datetime = "202308102400"

val localdatetime = LocalDateTime.parse(datetime, formatter)
println(datetime)
println(localdatetime.format(formatter))

Expected result:
LocalDateTime.parse throws an exception.
According to documentation, HH stands for hour-of-day (0-23), so 2400 is invalid. Exception is also thrown for input string 202308102401.

Actual result:
202308110000 is printed. Checked in a scratch in Android Studio and in Kotlin playground (link)


Solution

  • Turns out it is my fault for not reading documentation with enough attention... Thanks Marco F. for pointing me at what I missed.

    DateTimeResolver is created with ResolverStyle.SMART by default which performs sensible default for each field, e.g. interpreting 24:00 as "first moment of next day" or allows month-of-day values up to 31, silently converting to actual valid day values.

    Correct code to get the expected behavior:

    val INPUT_DATETIME_PATTERN = "uuuuMMddHHmm"
    val formatter = DateTimeFormatter
        .ofPattern(INPUT_DATETIME_PATTERN)
        .withResolverStyle(ResolverStyle.STRICT)
    
    val datetime = "202308102400"
    
    val localdatetime = LocalDateTime.parse(datetime, formatter)
    println(datetime)
    println(localdatetime.format(formatter))
    

    Note also that year specifier is changed from yyyy (year of era) to uuuu (year), because strict resolver requires an era to go with YearOfEra (source).