Rupesh
Rupesh

Reputation: 2667

23/12/2013 is mapping with MM/dd/yyyy format why, why not ParseException

Can anybody help?

public void dateCalender() throws ParseException{
        System.out.println(new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH).parse("120/12/2013").toString()); //OUTPUT (Unexpected): Mon Dec 12 00:00:00 IST 2022
        System.out.println(new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH).parse("23/12/2013").toString()); //OUTPUT (Unexpected): Wed Nov 12 00:00:00 IST 2014
        System.out.println(new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH).parse("Jan/12/2013").toString()); //OUTPUT (Expected): Unparseable date: "Jan/12/2013"
    }

Upvotes: 0

Views: 388

Answers (6)

Arvind Kumar Avinash
Arvind Kumar Avinash

Reputation: 79550

java.time

The question and the accepted answer use the java.util date-time API and their formatting API, SimpleDateFormat which was the right thing to do in 2013. In March 2014, the modern Date-Time API supplanted the legacy date-time API and since then it is strongly recommended to switch to java.time, the modern date-time API.

Solution using java.time, the modern Date-Time API:

The java.time is smart to catch most such problems without any explicit settings. A custom DateTimeFormatter is by default set to ResolverStyle#SMART which does not allow a month outside the range 1-12 or a day-of-month value beyond 31. However, it also means that 02/31/2022 can be parsed to 2022-02-28 with a DateTimeFormatter.ofPattern("MM/dd/uuuu"). It is only to disallow such a parsing that you need to set ResolverStyle.#STRICT.

Demo:

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Locale;

class Main {
    public static void main(String[] args) {
        DateTimeFormatter parser = DateTimeFormatter.ofPattern("MM/dd/uuuu", Locale.ENGLISH);
        String arr[] = {
                "120/12/2013", // 120 will be discarded against MM
                "23/12/2013", // Month can not be outside the range 1-12
                "Jan/12/2013", // Jan will discarded against MM. Requires MMM
                "12/31/2022", // Will be parsed normally
                "02/31/2022" // Will be parsed to 2022-02-28
        };
        for (String s : arr) {
            try {
                System.out.println("===========================");
                System.out.println("Trying to parse " + s + " using the format MM/dd/uuuu");
                System.out.println("Parsed to " + LocalDate.parse(s, parser));
            } catch (DateTimeParseException e) {
                System.out.println(e.getMessage());
                // throw e;
            }
        }
    }
}

Output:

===========================
Trying to parse 120/12/2013 using the format MM/dd/uuuu
Text '120/12/2013' could not be parsed at index 2
===========================
Trying to parse 23/12/2013 using the format MM/dd/uuuu
Text '23/12/2013' could not be parsed: Invalid value for MonthOfYear (valid values 1 - 12): 23
===========================
Trying to parse Jan/12/2013 using the format MM/dd/uuuu
Text 'Jan/12/2013' could not be parsed at index 0
===========================
Trying to parse 12/31/2022 using the format MM/dd/uuuu
Parsed to 2022-12-31
===========================
Trying to parse 02/31/2022 using the format MM/dd/uuuu
Parsed to 2022-02-28

ONLINE DEMO

Demo of ResolverStyle.#STRICT:

class Main {
    public static void main(String[] args) {
        DateTimeFormatter parser = DateTimeFormatter.ofPattern("MM/dd/uuuu", Locale.ENGLISH)
                .withResolverStyle(ResolverStyle.STRICT);
        String arr[] = {
                "12/31/2022", // Will be parsed normally
                "02/31/2022" // Will fail against ResolverStyle.STRICT check
        };
        for (String s : arr) {
            try {
                System.out.println("===========================");
                System.out.println("Trying to parse " + s + " using the format MM/dd/uuuu");
                System.out.println("Parsed to " + LocalDate.parse(s, parser));
            } catch (DateTimeParseException e) {
                System.out.println(e.getMessage());
                // throw e;
            }
        }
    }
}

Output:

===========================
Trying to parse 12/31/2022 using the format MM/dd/uuuu
Parsed to 2022-12-31
===========================
Trying to parse 02/31/2022 using the format MM/dd/uuuu
Text '02/31/2022' could not be parsed: Invalid date 'FEBRUARY 31'

ONLINE DEMO

Note: Here, you can use y instead of u but I prefer u to y.

Learn more about the modern Date-Time API from Trail: Date Time.

Upvotes: 1

Antoniossss
Antoniossss

Reputation: 32535

You have to invoke setLenient with false - otherwise SimpleDateFormat will try to "figure out" what month that is. So, first create SimpleDateFormat and invoke sdf.setLenient(false). Now when parsing, you will get exception.

Upvotes: 4

Masudul
Masudul

Reputation: 21981

According to docs , parsing is lenient, So you didn't get exception for invalid input. It converted to another value.

By default, parsing is lenient: If the input is not in the form used by this object's format method but can still be parsed as a date, then the parse succeeds. Clients may insist on strict adherence to the format by calling setLenient(false).


If you want to get java.text.ParseException: Unparseable date:, than apply setLenient(false); at SimpleDateFormat

    String dateStr="120/12/2013";
    SimpleDateFormat sdf=new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH);
    sdf.setLenient(false);
    try {
        Date d=sdf.parse(dateStr);
    } catch (ParseException ex) {
        ex.printStackTrace();
    }

Upvotes: 2

user2996174
user2996174

Reputation: 1481

You are using the format MM/dd/yyyy .So its taking Two positions

U try this way:

System.out.println(new SimpleDateFormat("MMM/dd/yyyy", Locale.ENGLISH).parse("Jan/12/2013").toString());

Here not throws unparsable exception but am not shoore about that is working or not

I think this will be wrong way every time using only MM/dd/yyyy format as "1/12/2013"

Upvotes: -1

zifnab06
zifnab06

Reputation: 76

On the first two:

MM/dd/yyyy 120/12/2013

The compiler will take this as '12/12/2013 + 118 months' and essentially solve for the correct date. In your example, it comes out as December 12, 2022 (12/12/2013 + 9 years).

MM/dd/yyyy 23/12/2013

The exact same thing happens. You get '12/12/2013 + 9 months', or 11/12/2014.

The third one isn't technically in the MM/dd/yyyy format. As from the other answers, you can do something like this:

SystemDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH);
sdf.setLenient(true);
sdf.parse("Jan/12/2013");
System.out.println(sdf.toString());

Upvotes: 1

devnull
devnull

Reputation: 123618

From the documentation:

public void setLenient(boolean lenient)

You need to set the format to be non-lenient.

Upvotes: 1

Related Questions