I am using NetBeans IDE 7.2.
I have two separate classes newDateTest.java and newDateMethod.java, I am currently using my method class to validate a date from a user input which I have used in my test class.
So far in my test class I have the following:
try
{
Prompt ="please enter a date in the format dd-mm-yyyy";
System.out.println(Prompt);
String inputDate = in.next();
isValid = newDateMethod.validDate(input, input, input);
if (isValid){
System.out.println("VALID DATE");
} else {
System.out.println("INVALID DATE");
}
} catch (ArrayIndexOutOfBoundsException oob) {
System.out.println(oob);
}
However I have no idea how to validate the date in my method class as I am fairly new to Java.
Can anyone come to a solution? The sort of thing I've been taught to use is Date Formatter but I'm not sure whether this is appropriate here? If so, I wouldn't know how to use it
Like this:
Date date = null;
String inputDate = "07-01-2013";
try {
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
formatter.setLenient(false);
date = formatter.parse(inputDate);
} catch (ParseException e) {
e.printStackTrace();
}
Updated on 13-Jul-2021:
I heartily agree with Ole V.V.'s comment below. All Java and Kotlin developers should prefer the java.time package.
I'll add a more modern example when time permits.
Have a look at SimpleDateFormat.parse(...) and do remember to surround with try-catch.
The standard JDK class for that is SimpleDateFormat:
DateFormat fmt = new SimpleDateFormat("yourformathere");
// use fmt.parse() to check for validity
Alternatively, I'd recommend using Joda Time's DateTimeFormat.
Rather than relying on exceptions which tend to have a small performance overhead, you can also use the DateValidator from the Apache commons routines package like this:
if (DateValidator.getInstance().validate(inputDate, "dd-MM-yyyy") != null) {
// Date is valid
}
else {
// Date is invalid
}
Small disclaimer though, I haven't looked at the implementation of the validate method and I'm not sure if it uses for instance the SimpleDateFormat...
java.time
I recommend that you use java.time, the modern Java date and time API, for your date work. It also gives you much preciser validation than the old SimpleDateFormat class used in some of the other answers.
String[] exampleInputStrings = { "07-01-2013", "07-01-017",
"07-01-2ooo", "32-01-2017", "7-1-2013", "07-01-2013 blabla" };
for (String inputDate : exampleInputStrings) {
try {
LocalDate date = LocalDate.parse(inputDate, DATE_FORMATTER);
System.out.println(inputDate + ": valid date: " + date );
} catch (DateTimeParseException dtpe) {
System.out.println(inputDate + ": invalid date: " + dtpe.getMessage());
}
}
Output from my example code is:
07-01-2013: valid date: 2013-01-07
07-01-017: invalid date: Text '07-01-017' could not be parsed at index 6
07-01-2ooo: invalid date: Text '07-01-2ooo' could not be parsed at index 6
32-01-2017: invalid date: Text '32-01-2017' could not be parsed: Invalid value for DayOfMonth (valid values 1 - 28/31): 32
7-1-2013: invalid date: Text '7-1-2013' could not be parsed at index 0
07-01-2013 blabla: invalid date: Text '07-01-2013 blabla' could not be parsed, unparsed text found at index 10
For a good validation you should probably add a range check. Use the isBefore and/or the isAfter method of LocalDate.
Also if you are going to do anything with the date more than validating it, you should keep the LocalDate from the parsing around in your program (not the string).
Link
Oracle tutorial: Date Time explaining how to use java.time.
You should use SimpleDateFormat.parse(String) method. if the passed date is of wrong format it throws an exception in which case you return false.
public boolean validateDate(String date) {
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
try {
sdf.parse(date);
return true;
}
catch(ParseException ex) {
return false;
}
}
One can use joda-time.
DateTimeFormat.forPattern(INPUTED_DATE_FORMAT);
//one can also use it with locale
DateTimeFormat.forPattern(USER_DATE_FORMAT).withLocale(locale);
fmt.parseDateTime(INPUTED_DATE);
If parseDateTime throw IllegalArgumentException then date is not valid.
Related
My requirement is to validate that a date String is in the correct format based on a set of valid formats specified.
Valid formats:
MM/dd/yy
MM/dd/yyyy
I created a simple test method that uses the Java 8 DateTimeFormatterBuilder to create a flexible formatter that supports multiple optional formats. Here is the code:
public static void test() {
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendOptional(DateTimeFormatter.ofPattern("MM/dd/yy"))
.appendOptional(DateTimeFormatter.ofPattern("MM/dd/yyyy"))
.toFormatter();
String dateString = "10/30/2017";
try {
LocalDate.parse(dateString, formatter);
System.out.println(dateString + " has a valid date format");
} catch (Exception e) {
System.out.println(dateString + " has an invalid date format");
}
}
When I run this, here is the output
10/30/2017 has an invalid date format
As you see in the code, the valid date formats are MM/dd/yy and MM/dd/yyyy.
My expectation was that the date 10/30/2017 should be valid as it matches MM/dd/yyyy. However, 10/30/2017 is being reported as invalid.
What is going wrong ? Why is this not working ?
I also tried
.appendOptional(DateTimeFormatter.ofPattern("MM/dd/yy[yy]"))
in place of
.appendOptional(DateTimeFormatter.ofPattern("MM/dd/yy"))
.appendOptional(DateTimeFormatter.ofPattern("MM/dd/yyyy"))
but still had the same issue.
This code runs as expected if I use:
String dateString = "10/30/17";
in place of
String dateString = "10/30/2017";
I have 2 questions
What is going wrong here ? Why is it not working for "10/30/2017" ?
Using Java 8, how to correctly create a flexible Date formatter (a formatter that supports multiple optional formats) ? I know the use of [] to create optional sections in the pattern string itself. I'm looking for something more similar to what I am trying (avoiding [] inside the pattern string and using separate optional clauses for each separate format string)
The formatter does not work the way you expect, the optional part means
if there is nothing extra attached to the first pattern (e.g., "MM/dd/yy"), that is fine,
if there is something extra, it needs to match the second pattern (e.g, "MM/dd/yyyy")
To make it a bit clearer, try to run the sample code below to understand it better:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendOptional(DateTimeFormatter.ofPattern("MM/dd/yy"))
.appendOptional(DateTimeFormatter.ofPattern("MM/dd/yyyy"))
.toFormatter();
String[] dateStrings = {
"10/30/17", // valid
"10/30/2017", // invalid
"10/30/1710/30/2017", // valid
"10/30/201710/30/17" // invalid
};
for (String dateString : dateStrings) {
try {
LocalDate.parse(dateString, formatter);
System.out.println(dateString + " has a valid date format");
} catch (Exception e) {
System.err.println(dateString + " has an invalid date format");
}
}
==
10/30/17 has a valid date format
10/30/1710/30/2017 has a valid date format
10/30/2017 has an invalid date format
10/30/201710/30/17 has an invalid date format
==
This is only a simple solution, if performance is of your concern, the validation by catching the parsing exception should be the last resort
you may check the string by length or regex first before doing the date string parsing
you may also replace the stream with a method containing a simple for loop, etc.
String[] patterns = { "MM/dd/yy", "MM/dd/yyyy" };
Map<String, DateTimeFormatter> formatters = Stream.of(patterns).collect(Collectors.toMap(
pattern -> pattern,
pattern -> new DateTimeFormatterBuilder().appendOptional(DateTimeFormatter.ofPattern(pattern)).toFormatter()
));
String dateString = "10/30/17";
boolean valid = formatters.entrySet().stream().anyMatch(entry -> {
// relying on catching parsing exception will have serious expense on performance
// a simple check will already improve a lot
if (dateString.length() == entry.getKey().length()) {
try {
LocalDate.parse(dateString, entry.getValue());
return true;
}
catch (DateTimeParseException e) {
// ignore or log it
}
}
return false;
});
The builder's appendValueReduced() method was designed to handle this case.
When parsing a complete value for a field, the formatter will treat it as an absolute value.
When parsing an partial value for a field, the formatter will interpret it relative to a base that you specify. For example, if you want two-digit years to be interpreted as being between 1970 and 2069, you can specify 1970 as your base. Here's an illustration:
LocalDate century = LocalDate.ofEpochDay(0); /* Beginning Jan. 1, 1970 */
DateTimeFormatter f = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ofPattern("MM/dd/"))
.appendValueReduced(ChronoField.YEAR, 2, 4, century)
.toFormatter();
System.out.println(LocalDate.parse("10/30/2017", f)); /* 2017-10-30 */
System.out.println(LocalDate.parse("10/30/17", f)); /* 2017-10-30 */
System.out.println(LocalDate.parse("12/28/1969", f)); /* 1969-12-28 */
System.out.println(LocalDate.parse("12/28/69", f)); /* 2069-12-28 */
This question already has answers here:
How to sanity check a date in Java
(24 answers)
Closed 5 years ago.
I'm programming a window where the user has to type a date on a input field but I don't know how to check if the day or month are coherent or not (like day between 1-31 and month between 1-12)
String string = "26/03/2017";
DateFormat format = new SimpleDateFormat("dd/MM/yyyy") ;
try {
Date date = format.parse(string);
} catch (ParseException e) {
e.printStackTrace();
}
This is the piece of code where I'm formatting the Date, but I have no idea to check what I said before.
Trying to parse a string like this: string = "36/03/2017"; can return a totally legal date object but an incorrect value respect the string.
for that case you can use the lenient flag of the class SimpleDateFormat, setting that flag to false will throw an exception for invalid strings representations of a date (e.g. 29 Feb 2017)
now, you can set the flag Lenient to false, and catch the exception
String string = "36/03/2017";
DateFormat format = new SimpleDateFormat("dd/MM/yyyy");
format.setLenient(false);
try {
Date date = format.parse(string);
System.out.println(date);
} catch (ParseException e) {
e.printStackTrace();
}
DateFormat has a property which named 'lenient' is default true.
You must set format.setLenient(false) to check validity of the date. if incorrect date is parsed, you get a ParseException.
2017 answer.
DateTimeFormatter format = DateTimeFormatter.ofPattern("dd/MM/uuuu")
.withResolverStyle(ResolverStyle.STRICT);
try {
LocalDate.parse(string, format);
} catch (DateTimeParseException e) {
System.out.println("Not a valid date: " + string);
}
While SimpleDateFormat has two degrees of strictness, lenient and non-lenient, DateTimeFormatter has three, strict, smart and lenient. For validation I recommend strict. Smart is the default, so we need to set it explicitly.
There are many more details in this answer.
I suggest to use regex. For your date format it should be something like:
(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](19|20)\d\d
You can also find more patterns and validate them here: http://html5pattern.com/Dates
I am using NetBeans IDE 7.2.
I have two separate classes newDateTest.java and newDateMethod.java, I am currently using my method class to validate a date from a user input which I have used in my test class.
So far in my test class I have the following:
try
{
Prompt ="please enter a date in the format dd-mm-yyyy";
System.out.println(Prompt);
String inputDate = in.next();
isValid = newDateMethod.validDate(input, input, input);
if (isValid){
System.out.println("VALID DATE");
} else {
System.out.println("INVALID DATE");
}
} catch (ArrayIndexOutOfBoundsException oob) {
System.out.println(oob);
}
However I have no idea how to validate the date in my method class as I am fairly new to Java.
Can anyone come to a solution? The sort of thing I've been taught to use is Date Formatter but I'm not sure whether this is appropriate here? If so, I wouldn't know how to use it
Like this:
Date date = null;
String inputDate = "07-01-2013";
try {
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
formatter.setLenient(false);
date = formatter.parse(inputDate);
} catch (ParseException e) {
e.printStackTrace();
}
Updated on 13-Jul-2021:
I heartily agree with Ole V.V.'s comment below. All Java and Kotlin developers should prefer the java.time package.
I'll add a more modern example when time permits.
Have a look at SimpleDateFormat.parse(...) and do remember to surround with try-catch.
The standard JDK class for that is SimpleDateFormat:
DateFormat fmt = new SimpleDateFormat("yourformathere");
// use fmt.parse() to check for validity
Alternatively, I'd recommend using Joda Time's DateTimeFormat.
Rather than relying on exceptions which tend to have a small performance overhead, you can also use the DateValidator from the Apache commons routines package like this:
if (DateValidator.getInstance().validate(inputDate, "dd-MM-yyyy") != null) {
// Date is valid
}
else {
// Date is invalid
}
Small disclaimer though, I haven't looked at the implementation of the validate method and I'm not sure if it uses for instance the SimpleDateFormat...
java.time
I recommend that you use java.time, the modern Java date and time API, for your date work. It also gives you much preciser validation than the old SimpleDateFormat class used in some of the other answers.
String[] exampleInputStrings = { "07-01-2013", "07-01-017",
"07-01-2ooo", "32-01-2017", "7-1-2013", "07-01-2013 blabla" };
for (String inputDate : exampleInputStrings) {
try {
LocalDate date = LocalDate.parse(inputDate, DATE_FORMATTER);
System.out.println(inputDate + ": valid date: " + date );
} catch (DateTimeParseException dtpe) {
System.out.println(inputDate + ": invalid date: " + dtpe.getMessage());
}
}
Output from my example code is:
07-01-2013: valid date: 2013-01-07
07-01-017: invalid date: Text '07-01-017' could not be parsed at index 6
07-01-2ooo: invalid date: Text '07-01-2ooo' could not be parsed at index 6
32-01-2017: invalid date: Text '32-01-2017' could not be parsed: Invalid value for DayOfMonth (valid values 1 - 28/31): 32
7-1-2013: invalid date: Text '7-1-2013' could not be parsed at index 0
07-01-2013 blabla: invalid date: Text '07-01-2013 blabla' could not be parsed, unparsed text found at index 10
For a good validation you should probably add a range check. Use the isBefore and/or the isAfter method of LocalDate.
Also if you are going to do anything with the date more than validating it, you should keep the LocalDate from the parsing around in your program (not the string).
Link
Oracle tutorial: Date Time explaining how to use java.time.
You should use SimpleDateFormat.parse(String) method. if the passed date is of wrong format it throws an exception in which case you return false.
public boolean validateDate(String date) {
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
try {
sdf.parse(date);
return true;
}
catch(ParseException ex) {
return false;
}
}
One can use joda-time.
DateTimeFormat.forPattern(INPUTED_DATE_FORMAT);
//one can also use it with locale
DateTimeFormat.forPattern(USER_DATE_FORMAT).withLocale(locale);
fmt.parseDateTime(INPUTED_DATE);
If parseDateTime throw IllegalArgumentException then date is not valid.
I need to Validate Date in a specified format where both the inputs will be given only in the runtime in JTextfield and will be changing dynamically. Below is the code I have tried:
Date dd = new Date();
DateFormat df = new SimpleDateFormat(Date_format_text.getText());
try {
df.setLenient(false);
Date d1 = df.parse(Lower_date_text.getText());
System.out.println("Correct");
validator_LD.setVisible(false);
} catch (ParseException p) {
validator_LD.setText("*Not in mentioned Format '" + df.format(dd) + "'");
validator_LD.setVisible(true);
System.out.println("Wrong");
}
The above is.. i get the Date specified and the format specified from the text field and try to parse according to the specified format. If it doesn't match it will throw exception.
But this is not working properly in some cases :
If I give the Date 02/01/20'and the Format - dd/MM/YYYY where it should throw an exception since I have given the year as 20 and the format is 'YYYY' but i doesn't give exception.
Kindly help me.. Thanks in advance
First, you may want to take a look at How to Use the Focus Subsystem, paying attention to Validating Input which might help.
Second, as pointed out by #eatSleepCode, you're not actually parsing the text of the field, but are simply formatting an existing Date, so it will never throw an exception...
simple_format = new SimpleDateFormat(Date_format_text.getText());
// This is simply formatting the dates...
String ss = simple_format.format(dates);
Instead, you need to use something more like...
String test = "02/01/20";
String format = "dd/MM/yyyy";
SimpleDateFormat sdf = new SimpleDateFormat(format);
sdf.setLenient(false);
try {
Date date = sdf.parse(test);
if (!sdf.format(date).equals(test)) {
throw new ParseException(test + " is not a valid format for " + format, 0);
}
} catch (ParseException ex) {
ex.printStackTrace();
}
What this does, is test's the parser capabilities of the formatter, but also checks the input against what the resulting parsed Date would be formatted to, if these don't match it throws a ParseException. This is the closes I've been able to get to a strict parser...
Also, YYYY used to represent the week in year, not the year...
Is there a good, strict date parser for Java? I have access to Joda-Time but I have yet to see this option. I found the "Is there a good date parser for Java" question, and while this is related it is sort of the opposite. Whereas that question was asking for a lenient, more fuzzy-logic and prone to human error parser, I would like a strict parser. For example, with both JodaTime (as far as I can tell) and simpleDateFormat, if you have a format "MM/dd/yyyy":
parse this: 40/40/4353
This becomes a valid date. I want a parser that knows that 40 is an invalid month and date. Surely some implementation of this exists in Java?
I don't see that Joda recognizes that as a valid date. Example:
strict = org.joda.time.format.DateTimeFormat.forPattern("MM/dd/yyyy")
try {
strict.parseDateTime('40/40/4353')
assert false
} catch (org.joda.time.IllegalFieldValueException e) {
assert 'Cannot parse "40/40/4353": Value 40 for monthOfYear must be in the range [1,12]' == e.message
}
As best as I can tell, neither does DateFormat with setLenient(false). Example:
try {
df = new java.text.SimpleDateFormat('MM/dd/yyyy')
df.setLenient(false)
df.parse('40/40/4353')
assert false
} catch (java.text.ParseException e) {
assert e.message =~ 'Unparseable'
}
Hope this helps!
A good way to do strict validation with DateFormat is re-formatting the parsed date and checking equality to the original string:
String myDateString = "87/88/9999";
Date myDate = dateFormat.parse(myDateString);
if (!myDateString.equals(df.format(myDate))){
throw new ParseException();
}
Works like a charm.
You can use the apache.commons.validator.routines.DateValidator to validate the date,if you do not want to use SimpleDateFormat.
Example :
public static Date validateDate(String value, String pattern) {
DateValidator validator = new DateValidator();
Date date = null;
if (pattern!=null) { //Pattern is passed
date = validator.validate(value, pattern);
} else {
date = validator.validate(value);
}
return date;
}
So if a null is returned it means that the date is not valid otherwise it's a valid date.This method is an alternative to using the SimpleDateFormat as you don't have to rely on exception being thrown to identify if it's a valid date or not.