简体   繁体   中英

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.

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.

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

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 (ie 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 .

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM