Reputation: 2667
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
Reputation: 79550
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
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'
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
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
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
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
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
Reputation: 123618
From the documentation:
public void setLenient(boolean lenient)
You need to set the format to be non-lenient.
Upvotes: 1