Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java LocalDateTime parse error [duplicate]

Been trying for 4 hours to figure this out.

:This works

String date = "Jul-01-2014 09:10:12";
LocalDateTime dt = LocalDateTime.parse(date, DateTimeFormatter.ofPattern("MMM-dd-yyyy HH:mm:ss", Locale.US));

:This will not

String date = "JUL-01-2014 09:10:12";
LocalDateTime dt = LocalDateTime.parse(date, DateTimeFormatter.ofPattern("MMM-dd-yyyy HH:mm:ss", Locale.US));

Only difference being the month all capitalized. Proper case of Jul works. Neither JUL or jul will work. I also tried pattern of 'LLL' with no luck. What am I missing??

like image 801
James Alfrey Avatar asked Dec 25 '14 02:12

James Alfrey


3 Answers

Well apparently I needed to spend 5 hours on this. While writing an extension to provide a workaround I discovered this.

    String date = "01-JUL-2014 09:10:12";

    DateTimeFormatterBuilder fmb = new DateTimeFormatterBuilder();
    fmb.parseCaseInsensitive();
    fmb.append(DateTimeFormatter.ofPattern("dd-MMM-yyyy HH:mm:ss"));

    LocalDateTime dt = LocalDateTime.parse(date, fmb.toFormatter());

Works great for all case styles.

like image 155
James Alfrey Avatar answered Oct 15 '22 14:10

James Alfrey


It doesn't look like that is supported by the official API.

Symbol  Meaning                     Presentation      Examples
  ------  -------                     ------------      -------
   G       era                         text              AD; Anno Domini; A
   u       year                        year              2004; 04
   y       year-of-era                 year              2004; 04
   D       day-of-year                 number            189
   M/L     month-of-year               number/text       7; 07; Jul; July; J
   d       day-of-month                number            10

The only option for month-of-year is there, and it does not explicitly mention any format supporting three capital letter months.

It's not terribly difficult to convert it back into a format that Java can respect though; it involves a wee bit of finagling the date and putting it back into a single String, though.

The solution below isn't as elegant or as clean as using a third party, but the added benefit is that one doesn't have to rely on the third party library for this code at all.

public String transformToNormalizedDateFormat(final String input) {
    String[] components = input.split("-");
    String month = components[0];
    if(month.length() > 3) {
        throw new IllegalArgumentException("Was not a date in \"MMM\" format: " + month);
    }
    // Only capitalize the first letter.
    final StringBuilder builder = new StringBuilder();
    builder.append(month.substring(0, 1).toUpperCase())
            .append(month.substring(1).toLowerCase())
            .append("-");
    final StringJoiner stringJoiner = new StringJoiner("-");
    Arrays.stream(components, 1, components.length).forEach(stringJoiner::add);
    builder.append(stringJoiner.toString());
    return builder.toString();
}
like image 26
Makoto Avatar answered Oct 15 '22 14:10

Makoto


Try using DateTimeFormatterBuilder and making parser case-insensitive. Don't forget to specify locale. Otherwise month abbreviation might not be parsed by MMM in default locale:

DateTimeFormatter format = new DateTimeFormatterBuilder()
  .parseCaseInsensitive()
  .appendPattern("dd-MMM-yyyy")
  .toFormatter(Locale.ENGLISH);

LocalDate.parse("03-jun-2015", format);
like image 26
ant Avatar answered Oct 15 '22 16:10

ant