'Validating date taken in from user in 3 different formats
Is there a way to validate these three date formats when they are taken in as an input?
- "03/03/2000"
- "03-03-2000"
- "3rd march 2000"
I managed to come up with a regex for the first 2.
\\d{2}/\\d{2}/\\d{4}
\\d{2}-\\d{2}-\\d{4}
Every approach I took to the third one using regex had a major flaw. regex will only check the format but not whether the date is a valid date. Is there a way to check the format and validity of these 3 date formats?
It is important for this application to take suffixes into account.
Solution 1:[1]
What the follow does is, tests to see if a given format can parse the String to a LocalDate OR LocalDateTime. If it can (do either), it will the compare the result of formatting either of those results against the original input, just to be sure (because date/time handling is just so much fun).
The intention is to not just determine if the values are within the specified formats, but also to verify if they are actually valid date/time values, because 99/99/0000 is a valid format, but isn't a valid date (except to SimpleDateFormat ????)
The parsing and comparisons are case insensitive.
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.util.Locale;
public final class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
String[] formats = new String[] {
"dd/MM/yyyy",
"dd-MM-yyyy",
"d MMMM yyyy"
};
String[] values = new String[] {
"03/03/2000",
"03-03-2000",
"3rd march 2000"
};
for (String value : values) {
String fixedValue = value.replaceAll("(?<=\\d)(st|nd|rd|th)", "");
boolean isValid = isValid(formats, fixedValue, Locale.ENGLISH);
System.out.println(value + " is valid = " + isValid);
}
}
public boolean isValid(String[] formats, String value, Locale locale) {
for (String format : formats) {
if (isValidDate(format, value, locale) || isValidDateTime(format, value, locale)) {
return true;
}
}
return false;
}
public boolean isValid(String format, String value, Locale locale) {
return isValidDate(format, value, locale) || isValidDateTime(format, value, locale);
}
public boolean isValidDateTime(String format, String value, Locale locale) {
try {
DateTimeFormatter fomatter = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern(format)
.toFormatter(locale);
LocalDateTime ldt = LocalDateTime.parse(value, fomatter);
return ldt.format(fomatter).equalsIgnoreCase(value);
} catch (DateTimeParseException | java.time.temporal.UnsupportedTemporalTypeException exp) {
return false;
}
}
public boolean isValidDate(String format, String value, Locale locale) {
try {
DateTimeFormatter fomatter = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern(format)
.toFormatter(locale);
LocalDate ld = LocalDate.parse(value, fomatter);
return ld.format(fomatter).equalsIgnoreCase(value);
} catch (DateTimeParseException | java.time.temporal.UnsupportedTemporalTypeException exp) {
return false;
}
}
}
which outputs
03/03/2000 is valid = true
03-03-2000 is valid = true
3rd march 2000 is valid = true
ps: Thanks Dev Parzival for the regular expression, that save a lot of time
Solution 2:[2]
use SimpleDateFormat to validate
Formatting date using SimpleDateFormat doesn't support suffix
(st, nd, rd and th) so we have to replace if they are present in the string .
Formatting using SimpleDateFormat
SimpleDateFormat is a concrete class for formatting and parsing dates in a locale-sensitive manner. It allows for formatting (date -> text), parsing (text -> date), and normalization.
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
class MainClass{
public static void main(String ... $){
System.out.println(isValidDate("03/03/2000"));
System.out.println(isValidDate("03-03-2000"));
System.out.println(isValidDate("3rd march 2000"));
}
public static boolean isValidDate(String str){
boolean match = false;
try{
Date date =new SimpleDateFormat("dd/MM/yyyy").parse(str.replaceAll("(?<=\\d)(st|nd|rd|th)", ""));
return true;
}catch(ParseException e){
//System.out.println(e);
match=false;
}
try{
Date date =new SimpleDateFormat("dd-MM-yyyy")
.parse(str.replaceAll("(?<=\\d)(st|nd|rd|th)", ""));
return true;
}catch(ParseException e){
//System.out.println(e);
match=false;
}
try{
Date date =new SimpleDateFormat("d MMMM yyyy")
.parse(str.replaceAll("(?<=\\d)(st|nd|rd|th)", ""));
return true;
}catch(ParseException e){
//System.out.println(e);
match = false;
}
return match;
}
}
Formatting using DateTimeForFormatter
import java.time.format.DateTimeFormatter;
import java.time.LocalDate;
import java.time.format.DateTimeParseException;
import java.time.format.DateTimeFormatterBuilder;
class MainClass{
public static void main(String ... $){
System.out.println(isValidDate("03/03/2000"));
System.out.println(isValidDate("03-03-2000"));
System.out.println(isValidDate("3rd march 2000"));
}
public static boolean isValidDate(final String str){
try{
DateTimeFormatter formatter =
DateTimeFormatter.ofPattern("dd/MM/yyyy");
LocalDate date = LocalDate.parse(str, formatter);
return true;
}catch(DateTimeParseException e){
//System.out.println(e);
}
try{
DateTimeFormatter formatter =
DateTimeFormatter.ofPattern("dd-MM-yyyy");
LocalDate date = LocalDate.parse(str, formatter);
return true;
}catch(DateTimeParseException e){
//System.out.println(e);
}
try{
DateTimeFormatter formatter =
new DateTimeFormatterBuilder().parseCaseInsensitive().appendPattern("d MMMM yyyy").toFormatter();
LocalDate date = LocalDate.parse(str.replaceAll("(?<=\\d)(st|nd|rd|th)", ""), formatter);
return true;
}catch(DateTimeParseException e){
//System.out.println(e);
}
return false;
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 |
