I am trying to do date validation. When the user enters something like: 2552533 Jan 2012 1340001 this gets parsed as: Wed Sep 03 07:41:00 EDT 9000. Here is my code:
SimpleDateFormat sdf = new SimpleDateFormat("dd MMM yyyy kkmm");
...
Date test;
try {
test = sdf.parse(dateString);
} catch (Exception e) {
...
Here dateString is a string that I'm trying to parse into a date. If the string isn't a valid date, like: 552533 Jan 2012 1340001, I was hoping for an error to be thrown. What am I doing wrong?
Try this (before parsing the actual date):
sdf.setLenient(false);
See also:
Make SimpleDateFormat.parse() fail on invalid dates (e.g. month is greater than 12)
SimpleDateFormat.parse does not throw any exception in case of error, it returns null. From the javadoc:
Returns:
A Date parsed from the string. In case of error, returns null.
Throws:
NullPointerException - if text or pos is null.
So you can do:
SimpleDateFormat sdf = new SimpleDateFormat("dd MMM yyyy kkmm");
...
Date test = sdf.parse(dateString);
if(test == null) {
// there was an error
}
As Tudor mentions, SimpleDateFormat does not throw an exception when it fails to parse. One alternative is DateUtils.parseDate90 (javadocs) from the Apache Commons available here.
Related
The full date received from the request is of this format
Wed Mar 11 2020 05:29:01 GMT+0100 (West Africa Standard Time)
Now I substringed it to this - Wed Mar 11 2020
date.substring(0,15))
To enable me to save the date, I am parsing it as below
SimpleDateFormat format = new SimpleDateFormat("YYYY-MM-dd", Locale.ENGLISH);
Date parsedDate = null;
try {
parsedDate = format.parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
When the code is ran, I get below error
java.text.ParseException: Unparseable date: "Wed Mar 11 2020"
I have also tried parsing with
SimpleDateFormat format = new SimpleDateFormat("EE MMM dd HH:mm:ss z yyyy",
Locale.ENGLISH);
based on SO answers and I am still getting date parsing error.
How can I parse this date - date.substring(0,15))
The format you need to match your date is EEE MMM dd yyyy e.g.
String date = "Wed Mar 11 2020 05:29:01 GMT+0100 (West Africa Standard Time)";
date = date.substring(0,15);
SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd yyyy");
Date parsedDate = null;
try {
parsedDate = format.parse(date);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(parsedDate);
SimpleDateFormat outformat = new SimpleDateFormat("yyyy-MM-dd");
System.out.println(outformat.format(parsedDate));
Output:
Wed Mar 11 00:00:00 CET 2020
2020-03-11
Three points:
Do use java.time, the modern Java date and time API, for your date and time work.
Rather than taking a substring of the string you receive, I’d prefer to parse the entire string.
Your format pattern string must match the string you are trying to parse (and vice versa). Exactly.
In code:
DateTimeFormatter formatter =
DateTimeFormatter.ofPattern(
"EEE MMM d uuuu HH:mm:ss 'GMT'xx (zzzz)", // Pattern to match your input strings.
Locale.UK // Locale determines human language used to parse name of month and such.
)
;
String dateString = "Wed Mar 11 2020 05:29:01 GMT+0100 (West Africa Standard Time)";
ZonedDateTime zonedDateTime = ZonedDateTime.parse(dateString, formatter);
Generate a string.
System.out.println( zonedDateTime.toString() );
Output from this snippet is:
2020-03-11T03:29:01+01:00[Africa/Lagos]
Use java.time. The modern API is sol much nicer to work with. The Date class that you used is poorly designed, and SimpleDateFormat notoriously troublesome. Don’t use any of those.
Parse the entire string. Taking a substring of length 15 will cause some readers of your code to wonder, some ask “WTF?”, some to use their precious time for counting to make sure that 15 is the correct length. Also taking a substring of length 15 is fragile unless you’re sure that the abbreviations for day of week and for month always have length three and day of month is always written with two digits (May 02, not May 2). Furthermore it’s easier to parse more than you need and throw information away later, than to parse just what you think you need and later discover that you needed one more bit.
Specifying the format. Since your string begins with a day of week abbreviation, you need a format pattern string that begins with the format pattern letter for day of week. In this case EEE (or E or EE) for the abbreviation (EEEE would have meant the day written in full, like Wednesday). So YYYY-MM-dd is all wrong. EE MMM dd HH:mm:ss z yyyy comes closer and can parse day of week, month and day of month. Then comes a space and a year in the input, but your format pattern string has yyyy for year at the end instead, so this is where parsing breaks for you. If writing the correct format pattern string teases (as it does for many), a trick is to try something and first use the formatter for formatting a date and time. If the result differs from the string we would like to parse, it usually gives us a hint about what’s wrong.
Link: Oracle tutorial: Date Time explaining how to use java.time.
Try this.
SimpleDateFormat sdf3 = new SimpleDateFormat("EEE MMM dd yyyy");
Date d1 = null;
try {
d1 = sdf3.parse("Wed Mar 30 2016");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(sdf3.format(d1));
}
Output:
Wed Mar 30 2016
First you need to control your computer language. According to your computer's language. You must write day's name and month's name in your computer's language
Actually you had better convert this 'Wed' according to your language.
My computer's language is turkish.
I used below code how to use day's name on date on java.
public static void main(String[] args) {
String sDate1 = "Per Mar-11-2020";
String sDate2 = "Perşembe Mar-11-2020";
Date date1;
try {
date1 = new SimpleDateFormat("EEE MMM-dd-yyyy").parse(sDate1);
System.out.println(sDate1+"\t\t"+date1);
date1 = new SimpleDateFormat("EEEEE MMM-dd-yyyy").parse(sDate2);
System.out.println(sDate2+"\t\t"+date1);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
output :
Per Mar-11-2020 Wed Mar 11 00:00:00 AST 2020
Perşembe Mar-11-2020 Wed Mar 11 00:00:00 AST 2020
Also you need to be carefull such as :
if your String is Per Mar-11-2020, you need to write EEE MMM-dd-yyyy.
Or
if your String is Per Mar 11 2020, you need to write EEE MMM dd yyyy.
Or
if your String is Per Mar/11/2020, you need to write EEE MMM/dd/yyyy.
I wanted to validate date in client side so I wrote the following code. But instead of getting an exception I am getting a proper date object for 31st of February date string, which is clearly an invalid date.
public class Test {
public static void main(String[] args) {
String dateFormat = "HH:mm:ss MM/dd/yyyy";
String dateString = "11:30:59 02/31/2015";
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(dateFormat, Locale.US);
try {
LocalDateTime date = LocalDateTime.parse(dateString, dateTimeFormatter);
System.out.println(date);
} catch (Exception e) {
// Throw invalid date message
}
}
}
Output : 2015-02-28T11:30:59
Does anyone know why LocalDateTime is parsing this date instead of throwing an exception.
You just need a strict ResolverStyle.
Parsing a text string occurs in two phases. Phase 1 is a basic text parse according to the fields added to the builder. Phase 2 resolves the parsed field-value pairs into date and/or time objects. This style is used to control how phase 2, resolving, happens.
Sample code - where withResolverStyle(ResolverStyle.STRICT) is the important change, along with the use of uuuu rather than yyyy (where uuuu is "year" and "yyyy" is "year of era", and therefore ambiguous):
import java.time.*;
import java.time.format.*;
import java.util.*;
public class Test {
public static void main(String[] args) {
String dateFormat = "HH:mm:ss MM/dd/uuuu";
String dateString = "11:30:59 02/31/2015";
DateTimeFormatter dateTimeFormatter = DateTimeFormatter
.ofPattern(dateFormat, Locale.US)
.withResolverStyle(ResolverStyle.STRICT);
try {
LocalDateTime date = LocalDateTime.parse(dateString, dateTimeFormatter);
System.out.println(date);
} catch (DateTimeParseException e) {
// Throw invalid date message
System.out.println("Exception was thrown");
}
}
}
The Java 8 DateTimeFormatter uses yyyy to mean YEAR_OF_ERA, and uuuu to mean YEAR. You need to modify your pattern string as follows:
String dateFormat = "HH:mm:ss MM/dd/uuuu";
The DateTimeFormatter defaults to using the SMART resolver style, but you want it to use the STRICT resolver style. Modify your dateTimeFormatter initialization code as follows:
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(dateFormat, Locale.US)
.withResolverStyle(ResolverStyle.STRICT);
It is not rounding down. February has never had 31 days, and it is impossible to use a validating date / time object to represent a day that doesn't exist.
As a result, it takes the invalid input and gives you the best approximation to the correct date (the last date of February that year).
SimpleDateFormat inherits from DateFormat which has a setLenient(boolean value) method on it. I would expect that if you called setLenient(true) prior to parsing, it would probably complain more, as detailed in the javadocs.
try {
SimpleDateFormat df = new java.text.SimpleDateFormat("HH:mm:ss MM/dd/yyyy");
df.setLenient(false);
System.out.println(df.parse("11:30:59 02/29/2015"));
} catch (java.text.ParseException e) {
System.out.println(e);
}
I found one solution to recognize date as a valid date with DateFormat.setLenient(boolean). If you try to parse any invalid date it will throws parse exception.
Edit:
Java 8, but this will raise exception if a month is not between 1 and 12, if a day is more than 32. Exactly not working. But for month its working.
try {
TemporalAccessor ta = DateTimeFormatter.ofPattern("HH:mm:ss MM/dd/yyyy").parse("11:30:59 02/32/2015");
} catch (Exception e) {
System.out.println(e);
}
Output:
java.time.format.DateTimeParseException: Text '11:30:59 02/32/2015' could not be
parsed: Invalid value for DayOfMonth (valid values 1 - 28/31): 32
LocalDateTime.parse will only throw an error if the String passed in contains invalid characters, a number of days exceeding 31 or a month exceeding 12.
For example, if you modified your code as such:
String dateString = "11:30:59 0zz2/31/2015";
an exception would be thrown caused by the invalid 'zz' characters within your given date. As to why it's 'rounding-down' the date so to speak, that I don't know.
Source: https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html#parse-java.lang.CharSequence-
Below is my code to parse the date using SimpleDateFormat with pattern:
String pattern = "yyyy-MM-dd";
SimpleDateFormat format = new SimpleDateFormat(pattern);
try {
Date date = format.parse("05-21-2030");
System.out.println(date);
} catch (ParseException e) {
e.printStackTrace();
}
You can see the date which I passed to parse is different from date format which is specified in SimpleDateFormat. In this case I was expecting kind of excpetion as format is different but it parsed successfully with some different date values. I got the output - Tue Mar 22 00:00:00 IST 12
When I pass the same format like 2030-05-21 it works fine.
Can you guys please let me know how can I prevent such things in my code?
Basically you want SimpleDateFormat to be strict, so set lenient to false.
SimpleDateFormat format = new SimpleDateFormat(pattern);
format.setLenient(false);
If you can afford using Java 8 time API, its formatter works as expected:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
try {
LocalDate date = LocalDate.parse("2030-05-21", formatter);
System.out.println(date);
LocalDate date2 = LocalDate.parse("05-21-2030", formatter);
System.out.println(date2);
} catch (DateTimeParseException e) {
e.printStackTrace();
}
Output:
2030-05-21
java.time.format.DateTimeParseException: Text '05-21-2030' could not be parsed at index 0
at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1947)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1849)
at java.time.LocalDate.parse(LocalDate.java:400)
at java8.Snippet.main(Snippet.java:25)
Take a look at my code:
try {
// String date = "30Jul2013";
SimpleDateFormat sdf = new SimpleDateFormat("ddMMMyyyy", Locale.ENGLISH);
Date d = sdf.parse(date);
SimpleDateFormat nsdf = new SimpleDateFormat("MMMM dd, yyyy h:mm a", Locale.ENGLISH);
String nd = nsdf.format(d);
System.out.println(nd);
return nd;
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Im am getting a error:
java.text.ParseException: Unparseable date: "2013-07-30 10:58:55.171"
at java.text.DateFormat.parse(DateFormat.java:337)
I would like to have an output of July 30, 2013 11:10 AM from the simpledateformat. There's LOCALE in my code. So what else should I do?
Thanks in advance!
try {
// String date = "30Jul2013";
SimpleDateFormat sdf = new SimpleDateFormat("ddMMMyyyy", Locale.ENGLISH);
Date d = sdf.parse(date);
Your date String variable line is commented out, so who's to know what String you're parsing? -- the JVM that's who.
As Robert Harvey points out, the String that you're actually trying to parse is printed for you in the exception message. If you print that String before you parse you'll also see that it's not what you expect it is and that the compiler's right.
In sum, you are somehow expecting that your sdf SimpleDateFormat object is formatting a String of a format similar to "30Jul2013", but the JVM is telling you that this simply is not so, that the String you are trying to parse in fact looks nothing like this, but rather is "2013-07-30 10:58:55.171".
I'm trying to execute this code:
Date date = null;
if (detailsBean.getDiscoveryProjectBean ().getCreatedDate ()==null ||
detailsBean.getDiscoveryProjectBean ().getCreatedDate ().equalsIgnoreCase(""))
{
projectDetails.getDiscoveryProject().setCreationTime(new Date());
}
else
{
try
{
date = new SimpleDateFormat (FormatUtils.simpleFormat).
parse (detailsBean.getDiscoveryProjectBean ().getCreatedDate ());
} catch (Exception e) {
throw new PanDaApplicationException (e.getMessage ());
}
projectDetails.getDiscoveryProject().setCreationTime(date);
}
in the try block a ParseException exception is thrown. I don't know the cause of that as the code seems fine, however. the definition of the FormatUtils.simpleFormat is public static final String simpleFormat = "dd-MMM-yyyy" and detailsBean.getDiscoveryProjectBean().getCreatedDate() have value like 28-Feb-2013
I really don't have any clues why this exception is thrown and I need help.
My guess is that the problem is the way that SimpleDateFormat uses your default locale - if your locale doesn't use "Feb" as an abbreviated month name, you'll have problems. So if all your data is actually in English, you might want:
DateFormat format = new SimpleDateFormat(FormatUtils.simpleFormat, Locale.US);
format.setTimeZone(...); // See below
date = format.parse(detailsBean.getDiscoveryProjectBean().getCreatedDate());
Note the part about setting the time zone. Again, SimpleDateFormat will use your system default if you don't specify anything else. (You'll get the instant of "midnight in the specified time zone" as the Date value.)
I would also strongly urge you to consider using Joda Time instead of the built-in Date/Calendar types - it's a much better date/time API.
Locale.setDefault (Locale.ROOT);
System.out.println (new SimpleDateFormat ("dd-MMM-yyyy").parse ("28-Feb-2013"));
Locale.setDefault (Locale.forLanguageTag ("ru"));
System.out.println (new SimpleDateFormat ("dd-MMM-yyyy").parse ("28-Feb-2013"));
For me output is:
Thu Feb 28 00:00:00 MSK 2013
Exception in thread "main" java.text.ParseException: Unparseable date: "28-Feb-2013"
at java.text.DateFormat.parse(DateFormat.java:357)
at DateFormat.main(DateFormat.java:19)
So the same date successfully parsed with ROOT locale, but failed with Russian.