Check for specific pattern - java

I want to check if a String is in certain pattern.
for example i want to check is a String matches the pattern: 2012-02-20.
I.E: xxxx-xx-xx when x is a number.
Is it possible? someone said regular expressions.

use this regex \d{4}-\d{2}-\d{2}
for checking use:
yourString.matches(regexString);

if you want to test if the date string is a valid date, better use SimpleDateFormat to check. don't use regex for that validation, how about month is 13? date is 50? leap years?
some example:
public boolean isValidDate(String dateString) {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
try {
df.parse(dateString);
return true;
} catch (ParseException e) {
return false;
}
}

You can do that with the SimpleDateFormat parse method:
final SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
boolean matchesDateFormat(String date)
{
try
{
format.parse(date);
return true;
}
catch(ParseException e)
{
return false;
}
}
Of course, if you later go on to parse the date anyway then you can skip this and just try to parse it.

You can check that the String follow the exact format of 4 digits, a dash -, 2 digits, a dash - and 2 digits with #burning_LEGION's regex. However, it doesn't check whether the String represents a valid date. You can specify 9999-99-99 and it will pass the validation.
Using SimpleDateFormat is the proper method to check that the String is a valid date and it follows a given format of representation. SimpleDateFormat, apart from formatting a date, can also be used to parse Date from String: parse(String), parse(String, ParsePosition).
By default, SimpleDateFormat is lenient, which means it will allow nonsensical dates such as 2013-025-234 to pass. Use setLenient(boolean lenient) to false will solve this problem.
However, another problem is that it will also ignore any garbage data that is after a valid date (e.g. 2012-03-23garbage#$%$#%). Setting lenient doesn't solve this problem. We need to check the last position with parse(String, ParsePosition) method.
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd");
// Make the parsing strict - otherwise, it is worse than regex solution
dateFormatter.setLenient(false);
Date date = null;
ParsePosition pos = new ParsePosition(0);
date = dateFormatter.parse(inputString, pos);
if (date != null && pos.getIndex() == inputString.length()) {
// These 3 points are ensured:
// - The string only contains the date.
// - The date follows the format strictly.
// - And the date is a valid one.
} else {
// Valid date but string contains other garbage
// Or the string has invalid date or garbage
}
SimpleDateFormat will allow 2013-1-5 to pass, which I think is a reasonable leniency. If you don't want this, you can do a check against the regex before plugging the String into the parse method.

You can check following code:
public void test() {
String REG_EXP = "(\\d{4}-[0,1]?\\d{1}-[0,1,2,3]?\\d{1})"; //yyyy-mm-dd formate this can not check boundary condition something like this... 1981-02-30
String REG_EXP1 = "(\\d{4}-\\d{2}-\\d{2})"; // if u just want xxxx-xx-xx where x is number
String input = "date1 1981-09-06 wrong date 9999-22-22 date2 1981-9-09 date3 1981-11-1 date4";
Pattern pattern = Pattern.compile(REG_EXP);
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
System.out.println(matcher.group());
}
}

Related

Java 8 DateTimeFormatterBuilder().appendOptional not working

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 */

groovy/java regex check if "yyyy.MM.dd" format

I have a string representing a date, for example "2010.12.25". How can I control if it is of "yyyy.MM.dd" format? There is no need to check the validness of the date.
You have the Regex, in Groovy, you can just do:
boolean match = "2010.12.12" ==~ /\d{4}\.\d{2}\.\d{2}/
use SimpleDateFormat to parse() the string, handling the exception to decide if it is a valid date string. don't use regex to check a date. e.g.:
2010.30.40
2010.13.34
try {
Date.parse('yyyy.MM.dd', '2013.12.21')
} catch(java.text.ParseException p) {
println "Unparseable Date"
}
​
You can also use Groovy Date parsing to check the accuracy of date format.
You can check the format of the date by using a SimpleDateFormat like this, because using regex for validating date formats is a very bad practice, IMHO.
String strDate = "2010.12.25";
DateFormat df = new SimpleDateFormat("yyyy.MM.dd");
try {
Date date = df.parse(strDate);
// If it comes here, then its a valid format
} catch (ParseException pe) {
// If it comes here, then its not a valid date of this format.
}
Try to this check this with method isValid(String dateStr),
boolean isValid(String dateStr) {
Matcher matcher=
Pattern.compile("\\d{4}\\.\\d{2}\\.\\d{2}").matcher(dateStr);
return matcher.matches();
}
Try this one
String a = "2010.12.12";
System.out.println(a.matches("\\d{4}\\.\\d{2}\\.\\d{2}"));
Output will be true

Checking date and its patten with expected pattern

I have a date and it's supposed pattern in string.
//True
String date ="2012-10-12 12:01:10.10.150";
String pattern = "yyyy-MM-dd hh:mm:ss.SSS";
//False
String date ="2012-10-12 12:01:10.150";
String pattern = "yyyy-MM-dd hh:mm:ss";
Now,i wanted to know whether the date variable has a proper date which satisfies a given pattern in string. In the above example True/False which I shows is the expected result.
I have tried with SimpleDateFormat(if it throws ParseException),but it will not going to work for 2nd example.
public boolean isValidDate(String date, String pattern) {
if (date == null)
return false;
SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
try {
dateFormat.parse(date.trim());
} catch (ParseException pe) {
return false;
}
return true;
}
I think you need to use both regex and SimpleDateFormat to achieve what you want
boolean validate(String date, String pattern) throws ParseException {
String regex = pattern.replaceAll("\\w", "\\\\d").replace(".", "\\.");
if (!date.matches(regex)) {
return false;
}
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
sdf.setLenient(false);
try {
sdf.parse(date);
} catch (Exception e) {
return false;
}
return true;
}
Use yyyy-MM-dd hh:mm:ss as the pattern for the second date.
String date = "2012-10-12 12:01:10";
String pattern = "yyyy-MM-dd hh:mm:ss";
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
Date parse = sdf.parse(date);
The capital S stands for milliseconds which your second string doesn't have. See the API.
From the SimpleDateFormat.parse() Java doc:
...parsing does not necessarily use all characters up to the end of the
string...
This means if your date is longer that the pattern it will still produce a valid Date instance. The other way around (e.g. your second example) the pattern is longer (more detailed) that the given date string, hence it doesn't produce a Date. Use this instead for your second example:
String pattern = "yyyy-MM-dd hh:mm:ss";

How to compare two date strings

I have two strings, the first one contains an actual date, and the second one contains a date format.
I want to compare both the strings. Here is my code:
String s1 = "01/02/2012";
String s2 = "dd/MM/yyyy";
if (s1.equalsIgnoreCase(s2)){
System.out.println("true");}
else {
System.out.println("false");}
I have tried with all the string methods (like compare(), equalTo(), etc.). It's always executing the else part, i.e. the condition is always "false".
Check Using Format
if(isValidDate("01/02/2012")){
System.out.println("true");}else{
System.out.println("false");}
}
public boolean isValidDate(String inDate) {
if (inDate == null)
return false;
// set the format to use as a constructor argument
SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
if (inDate.trim().length() != dateFormat.toPattern().length())
return false;
dateFormat.setLenient(false);
try {
// parse the inDate parameter
dateFormat.parse(inDate.trim());
} catch (ParseException pe) {
return false;
}
return true;
}
// date validation using SimpleDateFormat
// it will take a string and make sure it's in the proper
// format as defined by you, and it will also make sure that
// it's a legal date
public boolean isValidDate(String date)
{
// set date format, this can be changed to whatever format
// you want, MM-dd-yyyy, MM.dd.yyyy, dd.MM.yyyy etc.
// you can read more about it here:
// http://java.sun.com/j2se/1.4.2/docs/api/index.html
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
// declare and initialize testDate variable, this is what will hold
// our converted string
Date testDate = null;
// we will now try to parse the string into date form
try
{
testDate = sdf.parse(date);
}
// if the format of the string provided doesn't match the format we
// declared in SimpleDateFormat() we will get an exception
catch (ParseException e)
{
errorMessage = "the date you provided is in an invalid date" +
" format.";
return false;
}
// dateformat.parse will accept any date as long as it's in the format
// you defined, it simply rolls dates over, for example, december 32
// becomes jan 1 and december 0 becomes november 30
// This statement will make sure that once the string
// has been checked for proper formatting that the date is still the
// date that was entered, if it's not, we assume that the date is invalid
if (!sdf.format(testDate).equals(date))
{
errorMessage = "The date that you provided is invalid.";
return false;
}
// if we make it to here without getting an error it is assumed that
// the date was a valid one and that it's in the proper format
return true;
} // end isValidDate
Do it as below:
String s1 = "01/02/2012";
String s2 = "dd/MM/yyyy";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(s2);
try {
Date date = simpleDateFormat.parse(s1);
System.out.println(simpleDateFormat.format(date));
System.out.println("Parse successful. s1 matches with s2");
} catch (ParseException e) {
System.out.println("Parse failed. s1 differs by format.");
}
Please Note: a little warning
if you have s1="01/13/2012" parse will get successful, albeit it is not correct, because it will consider it as "01/01/2013" instead. So if you are ok with this, then proceed, else go ahead with your own implementation.

Convert String to Date - Date Validation

I am getting a null pointer exception when a user enters date in wrong format.
Method to convert String to Date
Date stringToDate(String dateString) {
Date returnDate = null;
if (dateString!= null && dateString.length() > 0 && isValidDate(dateString)) {
returnDate = dateFormat.parse(dateStr);
}
return returnDate;
}
and
boolean isValidDate(String date) {
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
Pattern datePattern = Pattern.compile("[0-9]{2}/[0-9]{2}/[0-9]{4}");
Matcher datePatternMatch = datePattern.matcher(date);
boolean datePatternMatchfound = datePatternMatch.matches();
if(date==null){
return false;
} else if(date!=null && date.length()>0){
if(datePatternMatchfound){
sdf.setLenient(false);
sdf.parse(date.trim());
}
return true;
} else {
return false;
}
}
I am just curious to know ....
1) what should be valid pattern for date?
2) if the user enters wrong date stringToDate method will certainly get failed and throw a null pointer exception. How to avoid that?
Any help would really be appreciated.
you are assuming the SimpleDateFormat(MM-dd-yyyyas the default pattern the user will input, either you should make sure your user can only enter in SimpleDateFormat, or you should make changes in isValidDate() to accept
Correct format of date representation depends entirely on your application and user locale. You can however limit the input format to a certain format and use it to parse and format the date input.
You can catch the ParseException thrown by the parse method and handle invalid cases inside your catch clause.
For example your code can be simplified to following:
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
Date stringToDate(String dateString) {
try {
Date returnDate = sdf.parse(dateString);
// do something with returnDate, if necessary
return returnDate;
} catch(ParseException e) {
// Date is not valid, handle invalid cases here..
return null; // Not a good practice, you probably would throw an Exception
}
}
And you can use the same formatter to display your values in the user interface by calling sdf.format(someDate) method and getting the String representation.
One thing is that you need to be more defensive in your validation method.
In the code you have shown, you do this:
Matcher datePatternMatch = datePattern.matcher(date);
before you check whether the date String is null. Pattern.matcher(null) results in NullPointerException.
So you need to move this code within your if (date != null) conditional block.
Aside from that, I don't see a benefit in validating the date String with a regex before validating it with a DateFormat. The regex validation is not giving you any additional benefit.
The valid pattern format depends for instance on the country setting of system.
You should put the content of your isValidDate() method in a try-catch block to avoid an exception.
By using Simple date format class we can validate if the string is date or not. You need to make sure to set the setLenient(false) to the simple date format object.
If it's not set you are end up with issue by rounding values.For example, a lenient GregorianCalendar interprets MONTH == JANUARY, DAY_OF_MONTH == 32 as February 1.
Example code:
http://www.vijayakumarg.co.in/2014/04/how-to-validate-date-string-in-java.html
public static boolean validateJavaDate(String strDate)
{
/*
* Set preferred date format,
* For example MM-dd-yyyy, MM.dd.yyyy,dd.MM.yyyy etc.*/
SimpleDateFormat sdfrmt = new SimpleDateFormat("MM/dd/yyyy");
sdfrmt.setLenient(false);
/* Create Date object */
Date javaDate = null;
/* parse the string into date form */
try
{
javaDate = sdfrmt.parse(strDate);
System.out.println("Date after validation: " + javaDate);
}
/* Date format is invalid */
catch (ParseException e)
{
System.out.println("The date you provided is in an " +"invalid date format.");
return false;
}
/* Return 'true' - since date is in valid format */
return true;
}

Categories

Resources