4

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.

9
  • use regular expression. Commented Feb 2, 2015 at 7:26
  • 3
    For that particular pattern, you could just check that the length of the input is 10. For variable-length patterns, it's slightly harder - there are alternative parse methods which allow you to see how much of the string has been parsed. (See parse(String, ParsePosition).) Commented Feb 2, 2015 at 7:29
  • @JonSkeet I also thought of that solution, but it seems more like an alternative. Commented Feb 2, 2015 at 7:34
  • @Jon, slighly better IMO is checking if the string contains a ':', ( in case a valid time somewhere strange is 10 long) but both are likely fine. Commented Feb 2, 2015 at 7:35
  • 1
    @user949300 I am pointing to different database columns based on the incoming string. Commented Feb 5, 2015 at 8:24

4 Answers 4

4
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.

Sign up to request clarification or add additional context in comments.

7 Comments

Seems like overkill when checking length 10 or for presence of. ':' also work. What would this regex catch where those fail?
@user949300 eg for input
O.k., yes, in general case, or if user we're typing, you'd want a regex. However, OP specified that the Strings are already highly limited and structured.
@user949300 i agree with your points, reading OP question, his solution did not work, why it did not worked explained by San Krish, he also wanted to have alternate solutions, which can be many considering your input and considering OP input is very well structured.
Also this allows invalid dates. If you're not really going to validate that it's a date, why not just check the length?
|
3

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());
    }
}

4 Comments

Thanks jon for the idea. I think that comparing pattern length and date string length is the best possible solution so far.
@SahilJain: That's fine if it's a fixed-length pattern. If you've got a pattern like "EEE dd MMM yyyy" then it won't work.
I might quibble that this fails (I think???) for an input with a space at the end, which may be common, and you may wish to consider "legal". If so, be sure to call trim() first.
@user949300: I would want it to fail in that case, personally - it's not "just a date" at that point. But yes, you can always trim it...
1

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.

Comments

0

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

2 Comments

Yes, i am understanding what java is doing there. But i am looking for a good solution for my problem and also want to understand why does java does not check for whole string. I tried to set lenient to false also, still not able to find the desired output
Have you read the answers in the post linked , it will make you clear . comment if you dont understand :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.