Search code examples
javajava-time

Java DateTimeFormatter problems


I have the following method, which takes a date string and tries for formate it to a LocalDateTime object:

(Locale is Norwegian)

public static LocalDateTime parseDatoLocalDateTime2(String datoString, String pattern, String language) {
    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
        .parseCaseInsensitive()
        .appendPattern(pattern)
        .toFormatter(Locale.forLanguageTag(language));
    return LocalDateTime.parse(datoString, formatter);
}

As far as I know, these are the correct "format codes" to use:

yyyy = 2024
yy = 24
MMMM = April
MMM = Apr
MM = 04
dd = 09
d = 9

So, this works:

String testdato1 = "8. 04. 2024 15:32";
parseDatoLocalDateTime2(testdato1, "d. MM. yyyy HH:mm", "no");

String testdato2 = "8. april 2024 15:32";
parseDatoLocalDateTime2(testdato2, "d. MMMM yyyy HH:mm", "no");

How come this does NOT work?

String testdato3 = "8. apr 2024 15:32";
parseDatoLocalDateTime2(testdato3, "d. MMM yyyy HH:mm", "no");

This fails with

java.time.format.DateTimeParseException: Text '8. apr 2024 15:32' could not be parsed at index 3

But why? As far as I can find out, "MMM" is the short name of the month ("apr", "jul" etc.).

I even went "basic", or "idiot", and asked ChatGTP:

Me: Can you show me how to use Java DateTimeFormatter to parse this string into a LocalDateTime object with Norwegian locale: "8. apr. 2024 15:32"

ChatGTP:

String dateString = "8. apr. 2024 15:32";
// Define the formatter pattern with Norwegian locale
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d. MMM. yyyy HH:mm", new Locale("no"));
    
// Parse the string into a LocalDateTime object
LocalDateTime dateTime = LocalDateTime.parse(dateString, formatter);
    
// Print the parsed LocalDateTime object
System.out.println(dateTime);

And even THIS code doesn't work for me. It fails more or less in the same way:

Text '8. apr. 2024 15:32' could not be parsed at index 7

Solution

  • When you check the opposite direction. Use your formatter to generate text to verify the human language and cultural norms of your specified locale.

    import java.time.format.DateTimeFormatter;
    import java.time.format.DateTimeFormatterBuilder;
    import java.time.LocalDateTime;
    
    DateTimeFormatter formatter = new DateTimeFormatterBuilder().
        parseCaseInsensitive().
        appendPattern("d. MMM. yyyy HH:mm").
        toFormatter(Locale.forLanguageTag("no"));
    
    System.out.println(formatter.format(LocalDateTime.now()));
    

    The output of this snippet (e.g. tested in jshell) is on my machine and at my local time:

    8. apr.. 2024 16:29
    

    So the MMM translates to apr. and when you add the . after that, you tell the parser to expect a second dot.

    Other way round:

    DateTimeFormatter formatterIn = new DateTimeFormatterBuilder().
        parseCaseInsensitive().
        appendPattern("d. MMM yyyy HH:mm").
        toFormatter(Locale.forLanguageTag("no"));
    formatterIn.parse("8. apr. 2024 16:29")
    

    That works fine without exception. Note that after the MMM in the format string I didn't add an extra dot.