50

I am using Java 8 to parse the the date and find difference between two dates.

Here is my snippet:

String date1 ="01-JAN-2017";
String date2 = "02-FEB-2017";

DateTimeFormatter df = DateTimeFormatter .ofPattern("DD-MMM-YYYY", en);
LocalDate  d1 = LocalDate.parse(date1, df);
LocalDate  d2 = LocalDate.parse(date2, df);

Long datediff = ChronoUnit.DAYS.between(d1,d2);

When I run I get the error:

java.time.format.DateTimeParseException: Text could not be parsed at index 3

Uma
  • 503
  • 1
  • 4
  • 5

6 Answers6

60

First of all, check the javadoc. The uppercase D represents the day-of-year field (not the day-of-month as you want), and uppercase Y represents the week-based-year field (not the year as you want). The correct patterns are the lowercase letters d and y.

Also, you're using month names in uppercase letters (JAN and FEB), so your formatter must be case insensitive (the default behaviour is to accept only values like Jan and Feb). And these month names are English abbreviations, so you must also use English locale to make sure it parses the names correctly (using java.util.Locale class).

So, your formatter should be created like this:

DateTimeFormatter df = new DateTimeFormatterBuilder()
    // case insensitive to parse JAN and FEB
    .parseCaseInsensitive()
    // add pattern
    .appendPattern("dd-MMM-yyyy")
    // create formatter (use English Locale to parse month names)
    .toFormatter(Locale.ENGLISH);

This will make your code work (and datediff will be 32).

  • 17
    Really great answer. Covers everything relevant and is right to the point. – Ole V.V. Jul 05 '17 at 19:59
  • 5
    Adding the Locale was critical and not obvious from my error message (DateTimeParseException: Text could not be parsed at index 0). Thanks for the tip! – Flic Jan 17 '18 at 22:08
24

The following code works. The problem is you are using "JAN" instead of "Jan". DateTimeFormatter does not recognize that it seems. and also change the pattern to "d-MMM-yyyy".

  String date1 ="01-Jan-2017";
  String date2 = "02-Feb-2017";

  DateTimeFormatter df = DateTimeFormatter.ofPattern("d-MMM-yyyy");
  LocalDate  d1 = LocalDate.parse(date1, df);
  LocalDate  d2 = LocalDate.parse(date2, df);

  Long datediff = ChronoUnit.DAYS.between(d1,d2);  

Source: https://www.mkyong.com/java8/java-8-how-to-convert-string-to-localdate/

Ramakanth Putta
  • 676
  • 4
  • 15
  • Thanks. It works. I have a another question. Will it take care of DayLightSaving time also ? – Uma Jul 05 '17 at 15:00
  • 2
    You won’t have any problems with daylight saving time, @Uma. Even if DST begins, say, on March 26, there is still exactly 1 day from March 25 to March 26. When using `LocalDate` it is completely ignored that there really are only 23 hours. In fact, `LocalDate` ignores any time zone and therefore any DST completely. – Ole V.V. Jul 05 '17 at 19:57
3
// DateTimeFormatterBuilder provides custom way to create a
    // formatter
    // It is Case Insensitive, Nov , nov and NOV will be treated same
    DateTimeFormatter f = new DateTimeFormatterBuilder().parseCaseInsensitive()
            .append(DateTimeFormatter.ofPattern("yyyy-MMM-dd")).toFormatter();
    try {
        LocalDate datetime = LocalDate.parse("2019-DeC-22", f);
        System.out.println(datetime); // 2019-12-22
    } catch (DateTimeParseException e) {
        // Exception handling message/mechanism/logging as per company standard
    }
3

Maybe Someone is looking for this it will work with date Format like 3/24/2022 or 11/24/2022

DateTimeFormatter.ofPattern("M/dd/yyyy")

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M/dd/yyyy");
       formatter = formatter.withLocale( Locale.US );  // Locale specifies human language for translating, and cultural norms for lowercase/uppercase and abbreviations and such. Example: Locale.US or Locale.CANADA_FRENCH
        LocalDate date = LocalDate.parse("3/24/2022", formatter);
        System.out.println(date);
1

Maybe you can use this wildcard,

 String d2arr[] = {
            "2016-12-21",
            "1/17/2016",
            "1/3/2016",
            "11/23/2016",
            "OCT 20 2016",
            "Oct 22 2016",
            "Oct 23", // default year is 2016
            "OCT 24",  // default year is 2016
    };

    DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder()
            .parseCaseInsensitive().parseLenient()
            .parseDefaulting(ChronoField.YEAR_OF_ERA, 2016L)
            .appendPattern("[yyyy-MM-dd]")
            .appendPattern("[M/dd/yyyy]")
            .appendPattern("[M/d/yyyy]")
            .appendPattern("[MM/dd/yyyy]")
            .appendPattern("[MMM dd yyyy]");

    DateTimeFormatter formatter2 = builder.toFormatter(Locale.ENGLISH);

https://coderanch.com/t/677142/java/DateTimeParseException-Text-parsed-unparsed-textenter link description here

取一个好的名字
  • 1,677
  • 14
  • 16
1

Try using DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd-LLL-yyyy",Locale.ENGLISH);

Lukas
  • 812
  • 1
  • 14
  • 43
  • I did try this and it hasn't worked for me. It only worked by using the parseCaseInsensitive() that was mentioned in other solutions. – eby Nov 03 '20 at 17:53