parse check doesn't work - java

hi guys i am using this method to check if a string can be converted to a date or not but it seems that it's not working, this is the code i wrote, the user inputs a date in this format dd/MM/YYYY then this is what happens for checking it
...
String date = JOptionPane.showInputDialog(frame,"Insert Date:");
if (date ==null) { return;}
while (!(isValidDate(date))) {
JOptionPane.showMessageDialog(frame, "Incorrect Date");
date = JOptionPane.showInputDialog(frame,"Insert Date:");
if (date ==null) { return;} }
String[] parts = date.split("/");
int year = Integer.parseInt(parts[2]);
int month = Integer.parseInt(parts[1]);
int day = Integer.parseInt(parts[0]);
...
and this is the method for check the date
public boolean isValidDate(String dateString) {
SimpleDateFormat df = new SimpleDateFormat("dd/MM/YYYY");
if (dateString.length() != "ddMMYYYY".length()) {
return false; }
try {
df.parse(dateString);
return true;
} catch (ParseException e) {
return false;
}
this seems not to work cause it always goes into the while block whatever i insert in the input, what is the problem with this code ?
EDIT
fixed the error on the condition
if (dateString.length() != "ddMMYYYY".length())
now i got another problem it accepts values like 54/12/2030 which obvioiusly are not a date format

Your if condition seems to be wrong... This is how it should be.
if (dateString.length() != "dd/MM/YYYY".length()) return false;
if input date is 22/07/1986 obviously it's length will be more than length of ddMMYYYY because of missing slashes.
df.setLenient(false); Will ensure that it won't roll over for invalid dates. Just put thiss line after you created df object.

This is a very good reason for why you should use a static final define rather than repeating the same string throughout your code. You are comparing against one string and parsing against another, so the two are never going to match.
I also don't understand why you would go through SimpleDateFormat to parse a Date (which has things like year, month etc available as method calls) and then throw that away in order to parse the String again by hand.
Just rename isValidDate to parseDate, have it return a Date object or null if not valid, and have the while loop continue so long as the Date returned is null.

For one thing, you want your date to be separated by / in most places, but you check if the string has the same length as "ddMMYYYY". You should probably change your isValidDate() method to include the slashes (and a trailing close-brace):
public boolean isValidDate(String dateString) {
SimpleDateFormat df = new SimpleDateFormat("dd/MM/YYYY");
if (dateString.length() != "dd/MM/YYYY".length()) {
return false;
}
try {
df.parse(dateString);
return true;
} catch (ParseException e) {
return false;
}
}

for last problem i had referring to values like 54/77/4444 i changed the YYYY to yyyy and it worked

Related

Prevent SimpleDateFormat From Matching Strings With Extraneous Characters

I'm using the following code to categorize whether or not the data type of text input is a date:
private boolean isDate(String val)
{
//These are the only formats dates will have
String[] formatList = {"MM/dd/yyyy", "MM-dd-yyyy", "MMM/dd/yyyy", "dd-MMM-yyyy"};
SimpleDateFormat dateFormat = new SimpleDateFormat();
dateFormat.setLenient(false);
dateFormat.
//Loop through formats in formatList, and if one matches the string return true
for (String str:formatList)
{
try
{
dateFormat.applyPattern(str);
dateFormat.parse(val.trim());
} catch (ParseException pe)
{
continue;
}
return true;
}
return false;
}
This method is called in a switch statement along with other function like isNumber, isDatetime, isVarchar2, etc. When I pass the value '4/05/2013 23:54' which is a datetime, the SimpleDateFormat object successfully parses it. I assume this is because it performs a regex match. This means I have to call isDate after isDatetime or nothing will ever be categorized as a datetime. Is there a simple way to get SimpleDateFormat to strictly match (ie, choke when there are extra characters)?
I would like to use java.time API from Java8+ with only one pattern like so :
private boolean isDate(String dateString) {
DateTimeFormatter format =
DateTimeFormatter.ofPattern(
"[M/d/uuuu][M-d-uuuu][MMM/d/uuuu][d-MMM-uuuu]"
);
try {
LocalDate.parse(dateString, format);
return true;
}catch (DateTimeParseException e){
return false;
}
}
where [M/d/uuuu][M-d-uuuu][MMM/d/uuuu][d-MMM-uuuu] means to match either M/d/uuuu or M-d-uuuu or MMM/d/uuuu or d-MMM-uuuu
If you read the documentation, i.e. the javadoc of parse, you'd see:
Parses text from the beginning of the given string to produce a date. The method may not use the entire text of the given string.
See the parse(String, ParsePosition) method for more information on date parsing.
The javadoc of the other method says:
Parameters:
source - The date/time string to be parsed
pos - On input, the position at which to start parsing; on output, the position at which parsing terminated, or the start position if the parse failed.
So, to ensure the entire text matches the date format, use the second method and check the ending parse position.
This also has the beneficial effect of not using exceptions for control flow.
private static boolean isDate(String val) {
String trimmedVal = val.trim();
//These are the only formats dates will have
String[] formatList = {"MM/dd/yyyy", "MM-dd-yyyy", "MMM/dd/yyyy", "dd-MMM-yyyy"};
SimpleDateFormat dateFormat = new SimpleDateFormat();
dateFormat.setLenient(false);
ParsePosition pos = new ParsePosition(0);
for (String str : formatList) {
pos.setIndex(0);
dateFormat.applyPattern(str);
dateFormat.parse(trimmedVal, pos);
if (pos.getIndex() == trimmedVal.length())
return true; // full text parsed without error
}
return false;
}
Test
System.out.println(isDate("12/31/2018"));
System.out.println(isDate("12-31-2018"));
System.out.println(isDate("Dec/31/2018"));
System.out.println(isDate("31-Dec-2018"));
System.out.println(isDate("4/05/2013"));
System.out.println(isDate("4/05/2013 23:54"));
Output
true
true
true
true
true
false

Exception while validating a date string in Java

I have found nice function which is validating the format and correctness of date String. I wanted to upgrade it to validate only >= 1900 years.
So this is what I found:
public boolean isDateValid(String date) {
try {
DateFormat df = new SimpleDateFormat("dd-MM-yyyy");
df.setLenient(false);
df.parse(date);
return true;
} catch (ParseException e) {
return false;
}
}
And this is my upgraded version:
public boolean isDateValid(String date) {
try {
DateFormat df = new SimpleDateFormat("dd-MM-yyyy");
df.setLenient(false);
df.parse(date);
Integer year = Integer.parseInt(date.substring(6, 10));
if (year>= 1900)
return true;
else
return false;
} catch (ParseException e) {
return false;
}
}
So instead of returning true I am checking if the year variable is greater or equal to 1900. The problem is when I run this function with "12-12-1xxx" (edit: or "12-12-1abc"). NumberFormatException is thrown while parsing year String to int. It definitely should not happen because ParseException should be thrown first, breaking the try {} block.
It looks like validation from first listing does not work properly because it accepts every "yyyy" part which begins with a number. Yet everything works fine for "12-12-xxxx" (edit: or "12-12-abcd").
EDIT:
Stop voting down my question and focus while you are reading. The question is very clear: why new SimpleDateFormat("dd-MM-yyyy").parse("12-12-1xxx") does not throw a ParseException?
As I understand from javadoc the SimpleDateFormat will take 1 as valid part of the year and will parse it. Instead you can try to validate date with regular expressions. You can find some examples here Regex to validate date format dd/mm/yyyy
The documentation of the parse method is:
Parses text from the beginning of the given string to produce a date.
The method may not use the entire text of the given string.
Because the whole string does not need to be used, then "12-12-1xxx" is actually parsed as "12-12-1", and you get a year 1 date.
Instead of using the substring, you could use the result of the parse method to get the year. getYear is depreciated and returns an offset from 1900 so you might want to convert to a Calendar or LocalDate first.
public boolean isDateValid(String date) {
try {
DateFormat df = new SimpleDateFormat("dd-MM-yyyy");
df.setLenient(false);
Date parsed = df.parse(date);
int year = parsed.getYear() + 1900;
if (year >= 1900)
return true;
else
return false;
} catch (ParseException e) {
return false;
}
}
I have check your function, and find below details.
If you will pass 12-12-1xxx in main function then also you will get true it will not return false even when I print the date output which is converted by df.parse(date) is Oct 10 00:00:00 GMT 2.
So you will not get parse exception anytime for this,
Suggestion
Either you change ParseException by Exception or also use catch for NumberFormatException as below.
public boolean isDateValid(String date) {
try {
DateFormat df = new SimpleDateFormat("dd-MM-yyyy");
df.setLenient(false);
df.parse(date);
Integer year = Integer.parseInt(date.substring(6, 10));
if (year>= 1900)
return true;
else
return false;
} catch (Exception e) { // Use Exception or if you want ParseException then use below commented code
return false;
}
/*catch (NumberFormatException nfe) { // Use this if you use ParseException
return false;
}*/
}
If anybody is interested in how the code should look like, here it is:
public boolean isDateValid(String date, String format) {
if (date.length()!=format.length())
return false;
try {
DateFormat df = new SimpleDateFormat(format);
df.setLenient(false);
df.parse(date); // exception is not thrown if day and month is
// correct AND the first char of year is a digit
// so if we have correct day and correct month
// and we know the year has 4 chars we can try to parse it
Integer year = Integer.parseInt(date.substring(6, 10));
if (year>= 1900 && year<=2015) // here we know that the year is 4 digit integer
return true; // and we can limit it
else
return false;
} catch (ParseException e) {
return false;
} catch (NumberFormatException e) {
return false;
}
}

Java - check if date format is acceptable and compare dates based on it

I want to create a simple function that gets 2 params - date format(dd/mm/yyyy, dd-mm-yyyy etc...) and a string that in this format(1/4/2015, 1-4-2015).
First of all is there a way to check if the format is acceptable by SimpleDateFormat and the next step if the dateInString is today, here is my code:
public boolean checkDate(String dateInString, String format){
boolean result = false;
SimpleDateFormat dateFormat = new SimpleDateFormat(format);
//parse the string to date
Date inputDate = dateFormat.parse(dateInString);
//check if the date is today using the format
//if the date is today then
result = true;
return result;
}
You could use this Utility class (DateUtils) with this implementation:
public boolean checkDate(String dateInString, String format){
try {
return DateUtils.isToday(new SimpleDateFormat(format).parse(dateInString));
} catch (ParseException e) {
return false;
}
}
For checking the format you could do something like this:
SimpleDateFormat dateFormat;
try {
dateFormat = new SimpleDateFormat(format);
}
catch(IllegalArgumentException e){
//handle wrong format
}
Check if date is today
dateInString.equals(dateFormat.format(new Date()))
Have a look at Joda Time Library which is much more convenient ;)
PS: Have not tested the, but thats roughly the way to go.
A cleaner way would be to split the method up e.g.
boolean isDateFormatValid(String format)
boolean isDateToday(String dateInString, String format)

How to find the given date is with in specified date range

Here is my code
boolean isWithinRange(String d)
{
boolean withinDate = false;
try
{
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date date = dateFormat.parse(d);
withinDate = !(date.before(startDate) || date.after(endDate));
}
catch (ParseException parseException)
{
}
return withinDate;
}
Inputs
2015-11-26
2015-11-26 - Copy
Both returning true but what i required is "2015-11-26" should be true and "2015-11-26 - Copy" should be false.
This is because SimpleDateFormat happily parses "2015-11-26" and ignores the " - Copy" part.
The javadoc states :
Parses text from the beginning of the given string to produce a date.
The method may not use the entire text of the given string.
To detect if the whole string has been used, instead use the parse(String source, ParsePosition pos) method. ParsePosition tells you where parsing stopped. Just compare this with the length of the original date string.
The problem here is we are passing the Date Format 'yyyy-MM-dd'. This will verify the given input upto this format.
For example,
static boolean isWithinRange(String d)
{
boolean withinDate = false;
try
{
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Date date = dateFormat.parse(d);
withinDate = !(date.before(startDate) || date.after(endDate));
}
catch (ParseException parseException)
{
parseException.printStackTrace();
}
return withinDate;
}
The above code throw exception because we are passing Date format as 'yyyy-MM-dd hh:mm:ss'. So this will find the hour minutes and seconds
just test if size is 10 before your test:
if (d.length!10) return false;
public static void main(String[] args) {
isWithinRange("2015-12-11 - Copy");
isWithinRange("2015-12-11");
}
public static boolean isWithinRange(String d) {
boolean withinDate = false;
try {
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
String dd = d.indexOf(" ") !=-1 ? d.substring(0, d.indexOf(" ")) : d; // Find valid String
if(d.equals(dd)){
Date date = dateFormat.parse(d);
withinDate = !(date.before(startDate)) || date.after(endDate)));
}else{
withinDate =false;
}
} catch (ParseException parseException) {
}
return withinDate;
}

SimpleDateFormat doesn't work as expected [duplicate]

This question already has answers here:
SimpleDateFormat parse(string str) doesn't throw an exception when str = 2011/12/12aaaaaaaaa?
(7 answers)
Closed 4 years ago.
I try to use this function but it doesn't work with this case '12/05/201a' somebody knows why happen this?
In my test I use this System.out.println(isThisDateValid("12/05/201a", "dd/MM/yyyy")); and the answer was true but I'm expected the result would be false because year contains letters.
public static boolean isThisDateValid(String dateToValidate, String dateFromat)
{
if (dateToValidate == null)
{
return false;
}
SimpleDateFormat sdf = new SimpleDateFormat(dateFromat);
sdf.setLenient(false);
try
{
//if not valid, it will throw ParseException
Date date = sdf.parse(dateToValidate);
System.out.println(date);
} catch (ParseException e)
{
e.printStackTrace();
return false;
}
return true;
}
DateFormat#parse doesn't necessarily use the entire string:
Parses text from the beginning of the given string to produce a date. The method may not use the entire text of the given string.
(my emphasis)
SimpleDateFormat's docs tell us that yyyy doesn't necessarily mean it will require four digits for a year:
Year:
...
For parsing, if the number of pattern letters is more than 2, the year is interpreted literally, regardless of the number of digits. So using the pattern "MM/dd/yyyy", "01/11/12" parses to Jan 11, 12 A.D.
So it's correct (if possibly surprising) that it parses that string in the year 201.
You can use parse(String,ParsePosition) to figure out whether the entire string has been consumed, or validate it with a regular expression before parsing. Here's a version that will check that the whole string has been parsed, and not just the first characters:
public static boolean isThisDateValid(String dateToValidate, String dateFormat) {
if (dateToValidate == null) {
return false;
}
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
sdf.setLenient(false);
ParsePosition position = new ParsePosition(0);
Date date = sdf.parse(dateToValidate, position);
return date != null && position.getIndex() == dateToValidate.length();
}

Categories