2

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

}
Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46
  • A `LocalDate` cannot contain a format. It always prints in ISO 8601 format. Does this answer your question? [How to format LocalDate object to MM/dd/yyyy and have format persist](https://stackoverflow.com/questions/39689866/how-to-format-localdate-object-to-mm-dd-yyyy-and-have-format-persist)? Maybe in combnation with this? [DateTimeFormatter Support for Single Digit Day of Month and Month of Year](https://stackoverflow.com/questions/27571377/datetimeformatter-support-for-single-digit-day-of-month-and-month-of-year) – Ole V.V. Jul 11 '22 at 08:45

1 Answers1

1

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.

Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46
  • @binary Are you sure that you're running `DateTimeFormatter` from the answer? There's no issue with parsing this string [*Proof - Online Demo*](https://www.jdoodle.com/ia/t6T) – Alexander Ivanchenko Jul 10 '22 at 20:42
  • It seems to ok in `M/d/yyyy` format, but how can I convert them to a desired format as `dd-MM-yyyy` ? –  Jul 10 '22 at 20:43
  • What about converting to `dd-MM-yyyy` format? –  Jul 10 '22 at 20:45
  • @binary You mean convert `LocalDate` a string formated like `dd-MM-yyyy`? For that you need to create another formatter [*see - online demo*](https://www.jdoodle.com/ia/t6U) – Alexander Ivanchenko Jul 10 '22 at 20:50
  • But it converts to string and I need `LocalDate`. Actually I tried this approach and faced this problem as I mentioned in my question, I need "LocalDate instead of String format". Any idea? –  Jul 10 '22 at 21:10
  • @binary What do you mean `I need LocalDate` ? I've explained to you how to parse a string into a `LocalDate`. It has its own method `toString()` and you **can't change** it. Makes sense? While you're printing an object like `LocalDate` using `System.out.println()` it will internally invoke `String.valueOf()` (*have a look at the source code if you're curious about it*) and string representation of this object according to its `toString()` method would be used. Are you still following me? Hence, if you're not satisfied with the `toString()` implementation, you need a `DateTimeFormatter`. – Alexander Ivanchenko Jul 10 '22 at 21:21
  • Chico, `date.format()` returns `String`, but I need LocalDate and tried to use something like that; `LocalDate.parse(csvRecord.get(Headers.BirthDate), formatter).format(formatter1)` , but it gives "*Required type: LocalDate, Provided: String*" error. –  Jul 10 '22 at 21:35
  • So, if I manege to use both of 2 formatter in `LocalDate.parse(csvRecord.get(Headers.BirthDate), formatter);` the problem will be fixed. In the demo, it is waiting String, but I need to provide `LocalDate`. Any idea? –  Jul 10 '22 at 21:35
  • 1
    @binary Read my previous message again **carefully**. – Alexander Ivanchenko Jul 11 '22 at 00:02
  • 2
    @binary It seems like you what you want to get an instance of `LocalDate` with a different behavior of `toString()`. It's **impossible**, is that clear? – Alexander Ivanchenko Jul 11 '22 at 00:06
  • Apparently, the `formatter` just describe the date format of the `date` we try to convert. `LocalDate.parse()` method convert this date to a default "*yyyy-dd-MM*" format. But as far as I see, it is not possible to convert it to the desired format in `LocalDate` as I need to save to database in that format. >>> –  Jul 11 '22 at 21:36
  • In this scene, would you suggest me to use another date format for my Entity instead of `LocalDate` ? Or is it better and commonly used to keep date data and I just keep them and need to format date while **displaying** ? Any idea amigo? –  Jul 11 '22 at 21:37
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/246384/discussion-between-alexander-ivanchenko-and-binary). – Alexander Ivanchenko Jul 12 '22 at 18:02