Sahil Jain
Sahil Jain

Reputation: 187

Check if a string contains only date

I have a string which can contain a date(yyyy-MM-dd) or date and time (yyyy-MM-dd HH:mm:ss) in respective formats.

I want to know which strings contains only date.

DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
System.out.println(dateFormat.parse("2015-02-02"));
System.out.println(dateFormat.parse("2015-02-02 23:23:23"));

In above code, both the strings are parsed successfully, whereas the format is same for only first.

Upvotes: 4

Views: 5737

Answers (4)

Arvind Kumar Avinash
Arvind Kumar Avinash

Reputation: 79075

java.time

The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.

Solution using java.time, the modern Date-Time API:

Let's first try to do it the way you have done:

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String[] arr = { "2015-02-02", "2015-02-02 23:23:23" };
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd", Locale.ENGLISH);

        for (String s : arr) {
            System.out.println("Attempting to parse '" + s + "':");
            LocalDate date = LocalDate.parse(s, dtf);
            System.out.println("Parsed successfully: " + date);
        }
    }
}

Output:

Attempting to parse '2015-02-02':
Parsed successfully: 2015-02-02
Attempting to parse '2015-02-02 23:23:23':
Exception in thread "main" java.time.format.DateTimeParseException: Text
'2015-02-02 23:23:23' could not be parsed, unparsed text found at index 10

As you can see, the java.time API correctly throws an exception informing you about the problem. SimpleDateFormat, on the other hand, parses the input string silently which has caused the problem that you have posted.

Thus, with the modern date-time API, you have two easy options:

  1. Simply catch the exception and say that the second input (i.e. 2015-02-02 23:23:23) is not a date string as per the specified date pattern.
  2. Use the function, DateTimeFormatter#parse(CharSequence, ParsePosition) with the ParsePosition index set to 0.

Given below is a demo of the second option:

import java.text.ParsePosition;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String[] arr = { "2015-02-02", "2015-02-02 23:23:23" };
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd", Locale.ENGLISH);

        for (String s : arr) {
            ParsePosition pp = new ParsePosition(0);
            LocalDate.from(dtf.parse(s, pp));
            if (pp.getIndex() < s.length()) {
                System.out.println("'" + s + "' is not a date string as per the specified date pattern.");
            }
        }
    }
}

Output:

'2015-02-02 23:23:23' is not a date string as per the specified date pattern.

ONLINE DEMO

Note: Never use SimpleDateFormat or DateTimeFormatter without a Locale.

Learn more about the modern Date-Time API from Trail: Date Time.


* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

Upvotes: 1

Jon Skeet
Jon Skeet

Reputation: 1500495

I would use the overload of parse which takes a ParsePosition - you can then check the position afterwards:

import java.util.*;
import java.text.*;

public class Test {

    public static void main(String[] args) throws Exception {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        dateFormat.setLenient(false);
        System.out.println(parseFully(dateFormat, "2015-02-02"));
        System.out.println(parseFully(dateFormat, "2015-02-02 23:23:23"));
    }

    private static Date parseFully(DateFormat format, String text) 
          throws ParseException {
        ParsePosition position = new ParsePosition(0);
        Date date = format.parse(text, position);
        if (position.getIndex() == text.length()) {
            return date;
        }
        if (date == null) {
            throw new ParseException("Date could not be parsed: " + text,
                                     position.getErrorIndex());
        }
        throw new ParseException("Date was parsed incompletely: " + text,
                                 position.getIndex());
    }
}

Upvotes: 3

Santhosh
Santhosh

Reputation: 8197

Once the desired format is reached , SimpleDateFormat doesnt format the rest of String . It is the reason why your second string is parsed.

This post SimpleDateFormat parse(string str) doesn't throw an exception when str = 2011/12/12aaaaaaaaa? may help you .

Also check the DateFormat#parse method in java docs

Upvotes: 0

Ankur Singhal
Ankur Singhal

Reputation: 26067

public static void main(String[] args) {
        String dateOnly = "2015-02-02";
        String dateAndTimeOnly = "2015-02-02 23:23:23";
        System.out.println("Date Only = " + validateDateFormat(dateOnly));
        System.out.println("Date And time Only = " + validateDateFormat(dateAndTimeOnly));
    }

    public static boolean validateDateFormat(String input) {

        return input.matches("([0-9]{4})-([0-9]{2})-([0-9]{2})");
    }

output

Date Only = true
Date And time Only = false

Regex is self explanatory - Input will be separated by -, ist part([0-9]{4}) can contain 4 digit , 2nd part can contain 2 digit [0-9]{2}, so as 3rd.

Upvotes: 4

Related Questions