Orby
Orby

Reputation: 418

Reformatting a Date from DD-MMM-YYYY to YYYYDDMM or YYYYMMDD

I'm trying to use Java 8 to re-format today's date but I'm getting the following error:

java.time.format.DateTimeParseException: Text '09-OCT-2017' could not be parsed: Unable to obtain LocalDate from TemporalAccessor: {WeekBasedYear[WeekFields[SUNDAY,1]]=2017, MonthOfYear=10, DayOfYear=9},ISO of type java.time.format.Parsed  

Code:

public static String formatDate(String inputDate, String inputDateFormat, String returnDateFormat){
    try {
        DateTimeFormatter inputFormatter = new DateTimeFormatterBuilder().parseCaseInsensitive().appendPattern(inputDateFormat).toFormatter(Locale.ENGLISH);            
        LocalDate localDate = LocalDate.parse(inputDate, inputFormatter);

        DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern(returnDateFormat);
        String formattedString = localDate.format(outputFormatter);
        return formattedString;
    } catch (DateTimeParseException dtpe) {
        log.error("A DateTimeParseException exception occured parsing the inputDate : " + inputDate + " and converting it to a " + returnDateFormat + " format. Exception is : " + dtpe);           
    }
    return null;
}

I previously tried using SimpleDateFormat, but the problem is my inputDateFormat format is always in uppercase DD-MMM-YYYY, which was giving me incorrect results, so I tried using parseCaseInsensitive() to ignore the case sensitivity.

Upvotes: 2

Views: 2543

Answers (2)

user7605325
user7605325

Reputation:

In the comments you told that the input format is DD-MMM-YYYY. According to javadoc, uppercase DD is the day of year field, and YYYY is the week based year field (which might be different from the year field).

You need to change them to lowercase dd (day of month) and yyyy (year of era). The parseCaseInsensitive() only takes care of the text fields - in this case, the month name (numbers are not affected by the case sensitivity - just because the month is in uppercase, it doesn't mean that the numbers patterns should also be).

The rest of the code is correct. Example (changing the format to yyyyMMdd):

String inputDate = "09-OCT-2017";
DateTimeFormatter inputFormatter = new DateTimeFormatterBuilder()
    .parseCaseInsensitive()
    // use "dd" for day of month and "yyyy" for year
    .appendPattern("dd-MMM-yyyy")
    .toFormatter(Locale.ENGLISH);
LocalDate localDate = LocalDate.parse(inputDate, inputFormatter);

// use "dd" for day of month and "yyyy" for year
DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
String formattedString = localDate.format(outputFormatter);
System.out.println(formattedString); // 20171009

The output of the code above is:

20171009


Regarding your other comment about not having control over the input pattern, one alternative is to manually replace the letters to their lowercase version:

String pattern = "DD-MMM-YYYY";
DateTimeFormatter inputFormatter = new DateTimeFormatterBuilder()
    .parseCaseInsensitive()
    // replace DD and YYYY with the lowercase versions
    .appendPattern(pattern.replace("DD", "dd").replaceAll("YYYY", "yyyy"))
    .toFormatter(Locale.ENGLISH);
// do the same for output format if needed

I don't think it needs a complex-replace-everything-in-one-step regex. Just calling the replace method multiple times can do the trick (unless you have really complex patterns that would require lots of different and complex calls to replace, but with only the cases you provided, that'll be enough).

Upvotes: 2

Alexander Heim
Alexander Heim

Reputation: 154

I hope I got you right. Formatting a String to LocalDate is acutally pretty simple. Your date format is that here right 09-Oct-2017? Now you just need use the split command to divide that into a day, month and year:

String[] tempStr = inputDate.split("-");
int year = Integer.parseInt(tempStr[2]);
int month = Integer.parseInt(tempStr[1]);
int day = Integer.parseInt(tempStr[0]);

After that it´s pretty easy to get that to LocalDate:

LocalDate ld = LocalDate.of(year, month, day);

I hope that helps.

Upvotes: -1

Related Questions