krishna singh
krishna singh

Reputation: 73

DateTimeFormatter unable to parse a Date String but SimpleDateFormat is able to

I am unable to parse this sample date string - "312015" representing "3rd Jan 2015" using LocalDate parse method. Could someone please assist.

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class TestDOB {

    public static void main(String[] args) throws ParseException {
        // TODO Auto-generated method stub

        String dateOfBirth = "312015";
        SimpleDateFormat sdf = new SimpleDateFormat("dMyyyy");
        System.out.println(sdf.parse(dateOfBirth)); 
        // The above outputs Sat Jan 03 00:00:00 CST 2015

        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dMyyyy").withLocale(Locale.getDefault());
        LocalDate dateTime = LocalDate.parse(dateOfBirth, dateFormatter);

        // The above parsing statement with LocalDate parse method runs into below error - 


    }

}

Error on console- 

Exception in thread "main" java.time.format.DateTimeParseException: Text '312015' could not be parsed at index 6
    at java.time.format.DateTimeFormatter.parseResolved0(Unknown Source)
    at java.time.format.DateTimeFormatter.parse(Unknown Source)
    at java.time.LocalDate.parse(Unknown Source)
    at TestDOB.main(TestDOB.java:30)

Upvotes: 0

Views: 756

Answers (1)

Anonymous
Anonymous

Reputation: 86139

DateTimeFormatterBuilder.appendValue(TemporalField, int)

I was surprised to find out that this is possible (it doesn’t make much sense to me).

    DateTimeFormatter dateFormatter = new DateTimeFormatterBuilder()
            .appendValue(ChronoField.DAY_OF_MONTH, 1)
            .appendValue(ChronoField.MONTH_OF_YEAR, 1)
            .appendValue(ChronoField.YEAR, 4)
            .toFormatter();

    String dateOfBirth = "312015";
    LocalDate dateTime = LocalDate.parse(dateOfBirth, dateFormatter);
    System.out.println(dateTime);

Output from this snippet is:

2015-01-03

It has some limitations that I would consider quite serious, though: It can only parse dates that are within days 1–9 of the month (not 10–31) in months January through September (not October–December) because it insists on day of month and month being only 1 digit each.

You may get rid of the limitation on day of month by leaving out the second argument, 1, from the first call to appendValue(). A similar trick will not work for the month, so the last quarter of the year is out of reach.

Why didn’t single d and single M work?

Why enforcing single d and single M doesn't work here? Am I missing something here?

To DateTimeFormatter one pattern letter for a numeric field is taken to mean “as many digits as it takes” (not “1 digit” as might have been expected). It’s not very well documented. There’s a hint in this sentence from the documentation:

If the count of letters is one, then the value is output using the minimum number of digits and without padding.

What happens is that parsing eats as many digits as it can for day of month (up to an internal limit of 19). In this case the entire string. Now it is unable to parse any month. This is the reason for the error message:

Text '312015' could not be parsed at index 6

Index 6 is the end of the string.

Documentation link

Documentation of DateTimeFormatter

Upvotes: 3

Related Questions