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;
}
Related
I have a project requirement. There are values in a .txt as -
02/01/2017 00:00:00
Now I need to have some rules to check if this value in the data file is of type Date. How can I do that? Thanks. I am new to Java so any help much appreciated. Thanks
Try to parse it to date. If it throws ParseException then it is not a date.
String dateString = "02/01/2017 00:00:00";
DateFormat df = new SimpleDateFormat("MM/dd/yyyy hh:mm:ss");
Date date;
try {
date = df.parse(dateString);
} catch (ParseException e) {
e.printStackTrace();
}
If you just want valid days, use non-lenient parsing:
String dateString = "02/28/2017 00:00:00";
DateFormat df = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
df.setLenient(false);
Date date;
try {
date = df.parse(dateString);
System.out.println(date);
} catch (ParseException e) {
e.printStackTrace();
}
This will throw an exception for non-existing days like the 31st of February
Methord 1
Date dt = new Date(); //this should your Dynamic object
if (dt.getClass().equals(new Date().getClass()))
{
//if its date object
}
Methord 2
if(dt instanceof Date){
//if its date object
}
Use this to check date
String sDate1="31/12/1998 00:00:00";
try{
Date date1=new SimpleDateFormat("dd/MM/yyyy hh:mm:ss").parse(sDate1); `
}
catch(Exception e)
{
//Not a date..
}
You can use regular expressions to check the format
public boolean isDate(String s){
String pattern= "([0-9]{2})/([0-9]{2})/([0-9]{4}) ([0-9]{2}):([0-9]{2}):([0-9]{2})";
return s.matches(pattern);}
Here’s the Java 8 solution (it can be made to work in Java 6 and 7 too when you use the ThreeTen Backport).
private static final DateTimeFormatter DATE_TIME_FORMAT
= DateTimeFormatter.ofPattern("MM/dd/uuuu HH:mm:ss")
.withResolverStyle(ResolverStyle.STRICT);
public static boolean hasTypeDate(String stringFromTxt) {
try {
DATE_TIME_FORMAT.parse(stringFromTxt);
return true;
} catch (DateTimeParseException dtpe) {
return false;
}
}
Stay away from SimpleDateFormat for new code. It has had its time, it’s been outdated for a while now.
If you intended the day of month first (if 02/01/2017 means January 2nd), you need the format pattern dd/MM/uuuu HH:mm:ss instead.
If you need to know which date and time was in the .txt, use:
LocalDateTime dateTime = LocalDateTime.parse(stringFromTxt, DATE_TIME_FORMAT);
Link: ThreeTen Backport: java.time classes for Java 6 and 7.
public static boolean isValidDate(String inDate) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
try {
dateFormat.parse(inDate.trim());
} catch (ParseException pe) {
return false;
}
return true;
}
public static void main(String[] args) {
String file = "/path/to/your/file.txt";
try {
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
String line;
while ((line = br.readLine()) != null) {
// do something with line
}
br.close();
isValidDate(line));
//do what you want :)
}
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;
}
}
I get a returned parsed JSON result with string values in the form of dates like "27-11-2012" which i parse to a date Object. my code for this is:
public Date stringToDateReport(String s){
//Log.d(TAG, "StringToDateReport here is " + s);
DateFormat format;
Date date = null;
//if(s.matches(""))
format = new SimpleDateFormat("dd-MMM-yyyy");
try {
date = (Date)format.parse(s);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
now my issue is, a feature has been implemented that sometimes the json only returns a year object like "2012" and is giving me an "ParseException: Unparseable date" as expected. I was thinking of using regex to match the string pattern and parse from there, but not sure how to do that. Any ideas and also anyway to parse only year in a DateFormat?
I'd try:
public Date stringToDateReport(String s){
DateFormat format;
Date date = null;
format = new SimpleDateFormat("dd-MM-yyyy");
if(s.length()==4) {
format = new SimpleDateFormat("yyyy");
}
try {
date = (Date)format.parse(s);
} catch (ParseException e) {
//you should do a real logging here
e.printStackTrace();
}
return date;
}
The logic behind is to check if the string is only 4 long, then apply the different format. In this case, this easy method is sufficient, but in other methods, the use of regexes might be required.
Try this code
public Date stringToDateReport(String s){
//Log.d(TAG, "StringToDateReport here is " + s);
DateFormat format;
Date date = null;
if(s.indexOf("-") < 0){
format = new SimpleDateFormat("yyyy");
}else{
format = new SimpleDateFormat("dd-MMM-yyyy");
}
try {
date = (Date)format.parse(s);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
Is there the possibility in have another format in the String s ? Or just these two?
public Date stringToDateReport(String strDate){
DateFormat formatnew SimpleDateFormat("dd-MM-yyyy");
Date date = null;
if(strDate.length()==4) {
format = new SimpleDateFormat("yyyy");
}
try {
date = (Date)format.parse(strDate);
} catch (ParseException e) {
//error parsing date
e.printStackTrace();
}
return date;
}
then call it like this :
String strDate = yourJson.getString("date");
Date d = stringToDateReport(strDate);
Here is an example:
public MyDate() throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/d");
sdf.setLenient(false);
String t1 = "2011/12/12aaa";
System.out.println(sdf.parse(t1));
}
2011/12/12aaa is not a valid date string. However the function prints "Mon Dec 12 00:00:00 PST 2011" and ParseException isn't thrown.
Can anyone tell me how to let SimpleDateFormat treat "2011/12/12aaa" as an invalid date string and throw an exception?
The JavaDoc on parse(...) states the following:
parsing does not necessarily use all characters up to the end of the string
It seems like you can't make SimpleDateFormat throw an exception, but you can do the following:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/d");
sdf.setLenient(false);
ParsePosition p = new ParsePosition( 0 );
String t1 = "2011/12/12aaa";
System.out.println(sdf.parse(t1,p));
if(p.getIndex() < t1.length()) {
throw new ParseException( t1, p.getIndex() );
}
Basically, you check whether the parse consumed the entire string and if not you have invalid input.
To chack whether a date is valid
The following method returns if the date is in valid otherwise it will return false.
public boolean isValidDate(String date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/d");
Date testDate = null;
try {
testDate = sdf.parse(date);
}
catch (ParseException e) {
return false;
}
if (!sdf.format(testDate).equals(date)) {
return false;
}
return true;
}
Have a look on the following class which can check whether the date is valid or not
** Sample Example**
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateValidCheck {
public static void main(String[] args) {
if(new DateValidCheck().isValidDate("2011/12/12aaa")){
System.out.println("...date is valid");
}else{
System.out.println("...date is invalid...");
}
}
public boolean isValidDate(String date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/d");
Date testDate = null;
try {
testDate = sdf.parse(date);
}
catch (ParseException e) {
return false;
}
if (!sdf.format(testDate).equals(date)) {
return false;
}
return true;
}
}
Java 8 LocalDate may be used:
public static boolean isDate(String date) {
try {
LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy/MM/dd"));
return true;
} catch (DateTimeParseException e) {
return false;
}
}
If input argument is "2011/12/12aaaaaaaaa", output is false;
If input argument is "2011/12/12", output is true
After it successfully parsed the entire pattern string SimpleDateFormat stops evaluating the data it was given to parse.
Take a look on the method documentation which says: ParseException if the beginning of the specified string cannot be parsed.
Method source code with javadoc:
/**
* 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.
* <p>
* See the {#link #parse(String, ParsePosition)} method for more information
* on date parsing.
*
* #param source A <code>String</code> whose beginning should be parsed.
* #return A <code>Date</code> parsed from the string.
* #exception ParseException if the beginning of the specified string
* cannot be parsed.
*/
public Date parse(String source) throws ParseException
{
ParsePosition pos = new ParsePosition(0);
Date result = parse(source, pos);
if (pos.index == 0)
throw new ParseException("Unparseable date: \"" + source + "\"" ,
pos.errorIndex);
return result;
}
You can use the ParsePosition class or the sdf.setLenient(false) function
Docs:
http://docs.oracle.com/javase/7/docs/api/java/text/ParsePosition.html
http://docs.oracle.com/javase/7/docs/api/java/text/DateFormat.html#setLenient(boolean)
Simply setting sdf.setLenient(false) will do the trick..
So, this is what I'm using as my isDate in Java.
public class Common {
public static final String DATE_PATTERN = "yyyy-MM-dd";
public static boolean isDate(String text) {
return isDate(text, DATE_PATTERN);
}
public static boolean isDate(String text, String date_pattern) {
String newDate = text.replace("T00:00:00", "");
SimpleDateFormat formatter = new SimpleDateFormat(date_pattern);
ParsePosition position = new ParsePosition(0);
formatter.parse(newDate, position);
formatter.setLenient(false);
if (position.getIndex() != newDate.length()) {
return false;
} else {
return true;
}
}
}
Here is my test code:
String fromDate = "";
if (Common.isDate(fromDate)) {
System.out.println("WHAT??????");
}
I see WHAT?????? printed every time. What am I missing here?
Thanks.
It is because your logic is not correct. newDate="", i.e. newDate.length()==0. As well as position.getIndex()==0 since the error is occuring at the very beginning of the string. You may test whether position.getErrorIndex()>=0.
The right way to check for a successful parse is to see, if the parse method returns a Date or null. Try this:
public static boolean isDate(String text, String date_pattern) {
String newDate = text.replace("T00:00:00", "");
SimpleDateFormat formatter = new SimpleDateFormat(date_pattern);
ParsePosition position = new ParsePosition(0);
formatter.setLenient(false);
return formatter.parse(newDate, position) != null;
}
Don't reinvent the wheel... use Joda Time ;)
DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd");
try {
DateTime dt = fmt.parseDateTime("blub235asde");
} catch (IllegalArgumentException e) {
e.printStackTrace();
return false;
}
return true;
Output:
java.lang.IllegalArgumentException: Invalid format: "blub235asde"
at org.joda.time.format.DateTimeFormatter.parseDateTime(DateTimeFormatter.java:673)
at Test.main(Test.java:21)