Cannot format in LocalDate instead of String in Java

Viewed 67

I have the following field in an entity:

private LocalDate birthDate;

I try to get date fields from CSV file using Apache Commons CSV and need to convert the read date field as LocalDate with the format I set in formatter:


// the read dates in the csv file are like that: 5/14/1974 

private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");

// I also tried using the same format
// private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy"); 

// code omittted for brevity

LocalDate.parse(csvRecord.get(Headers.BirthDate), formatter); // gives error

csvRecord.get(Headers.BirthDate) gives date correctly as 4/6/1986 in string format, but LocalDate.parse(...) cannot parse and gives "Text '4/6/1986' could not be parsed at index 0" error. So, what is wrong in my implementation? If I change date in csv file to 1986/6/1 then LocalDate.parse() working. Maybe I need to read the data in this format and then convert to desired format.

I can use some approach like that, but I need to get date as LocalDate format instead of String and that may be the factor causing error:


public static void main(String[] args) {

    Locale.setDefault(Locale.FRANCE);

    // no problem now, DateTimeFormatter always uses Locale.US
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d-MMM-yyyy", Locale.US);

    String date = "16-Aug-2016";

    LocalDate localDate = LocalDate.parse(date, formatter);

    System.out.println(localDate);  //default, print ISO_LOCAL_DATE

    System.out.println(formatter.format(localDate)); // print formatted date

}
1 Answers

You're getting an exception while parsing your data because the minimum number of digits in the sample string representing the month (and I guess the day of the month as well) is 1 but according to your pattern expected 2.

You need this formatter:

String date = "5/14/1974";

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M/d/yyyy");

System.out.println(LocalDate.parse(date, formatter));

On execution will print:

1974-05-14

Here's a quote from the documentation

Number: If the count of letters is one, then the value is output using the minimum number of digits and without padding. Otherwise, the count of digits is used as the width of the output field, with the value zero-padded as necessary. The following pattern letters have constraints on the count of letters. Only one letter of 'c' and 'F' can be specified. Up to two letters of 'd', 'H', 'h', 'K', 'k', 'm', and 's' can be specified. Up to three letters of 'D' can be specified.

If you want to produce a string from the parsed LocalDate formatted accordingly to another pattern, you can do it like that:

String dateString = "3/7/1999";
        
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M/d/yyyy");
    
LocalDate date = LocalDate.parse(dateString, formatter);
        
System.out.println(date);
    
DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("dd-MM-yyyy");
        
System.out.println(date.format(formatter1));

We can specify a Local using localizedBy() while creating a DateTimeFormatter but in this case there's no need in doing this, because formatting would be entirely governed by the pattern.

Related