Exception while validating a date string in Java - 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;
}
}

Related

Calculating the age of two LocalDates

Code:
public String Calcage(){
int age = 0;
try {
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
Date birth = sdf.parse(dateOfBirth);
Date d = new Date();
LocalDate birthday = birth.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
LocalDate now = d.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
age = Period.between(birthday, now).getYears();
} catch (ParseException e) {
e.printStackTrace();
}
return String.valueOf(age);
}
PROBLEM: It returns zero every time. The Date which I use for testing is 1985-01-07
If you are actually using 1985-01-07 it correctly returns 0 and should also throw a ParseException which will be caught from the catch block and the stacktrace will be printed.
Your code should work for 07.01.1985 and return 35.
if you want nevertheless to use 1985-01-07 you should edit the specified format to "yyyy-dd-MM" or "yyyy-MM-dd"

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;
}

parse check doesn't work

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

SimpleDateFormat and Date Comparison not given correct ouput

try {
Date sysDate = new SimpleDateFormat("dd/mm/yyyy").parse(_sysDate);
Date userDate = new SimpleDateFormat("dd/mm/yyyy").parse(_userDate);
if (userDate.compareTo(sysDate) > 0)
return false;
else
return true;
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Above is my following code snippet to check two dates which is greater or not.
When I am giving :
sysdate=12/9/2012 and userdate=11/9/2012 or 10/8/2012 or 15/9/2011 it is giving the correct output
But when I am giving :
sysdate=12/9/2012 and userdate=13/8/2012 or 15/7/2012 or 16/6/2012 it is giving incorrect output.
To my analysis I have come to this point if I choose any month between Jan' 12 to Aug '12 and select the day_of_month(i.e. 0,1,2,...,31) more than the current day_of_month (in this case 12), I always get an incorrect output.
Please suggest any possible solution.
The problem is the pattern which should be "dd/MM/yyyy" (with capital "MM" for month) instead of "dd/mm/yyyy" (with small "mm" which means minutes).
So, it should be as follows -
try {
DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
Date sysDate = df.parse(_sysDate);
Date userDate = df.parse(_userDate);
//...
try {
Date sysDate = new SimpleDateFormat("dd/MM/yyyy").parse(_sysDate);
Date userDate = new SimpleDateFormat("dd/MM/yyyy").parse(_userDate);
if (userDate.compareTo(sysDate) > 0)
return false;
else
return true;
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
The Date pattern is wrong dd/MM/yyyy instead of dd/mm/yyyy.
see this data format change like this dd/MM/yyyy in place of dd/mm/yyyy.
http://docs.oracle.com/javase/1.4.2/docs/api/java/text/SimpleDateFormat.html

Categories