3

I'm trying to find an elegant way to find out if the format of a date satisfies at least one of a list of given formats. Concrete I have to validate a date against these 3 formats: YYYY, YYYY-MM and YYYY-MM-dd.

I tried with an example found in another thread, but it doesn't work:

private boolean checkDateFormat( String dateString )
    {
        String[] possibleDateFormats = new String[] { "yyyy", "yyyy-MM", "yyyy-MM-dd" };

        boolean isValid = false;

        for ( String possibleDateFormat : possibleDateFormats )
        {
            try
            {
                SimpleDateFormat simpleDateFormant = new SimpleDateFormat( possibleDateFormat );
                simpleDateFormant.setLenient( false );
                simpleDateFormant.parse( dateString.trim() );
                isValid = true;
            }
            catch ( ParseException pe )
            {
            }
        }

        return isValid;
    }

Another way is to use regex, but it will be quite complicated to cover all the possibilities.

Still another way is to parse the string and separately check the year, month and day. Something like this:

String[] parts = dateString.split("-");
        boolean y = validateY(parts[0]);
        boolean m = parts.length>1 ? validateM(parts[1]) : true;
        boolean d = parts.length>2 ? validateD(parts[2]) : true;

        return y && m && d;

But I find it not so "elegant".

Other ideas?

EXAMPLES (why code 1 doesn't work):

String[] possibleDates = new String[] { "999", "1001", "2001", "1", "123-3", "1234-13", "2015-12-31", "2015-13-31", "2015-12-32", "1-1-1" };

for (String date : possibleDates)
{
    System.out.println(date + " : " + checkDateFormat(date));
}

OUTPUT(with and without break):

999 : true
1001 : true
2001 : true
1 : true
123-3 : true
1234-13 : true     <- 13 months??
2015-12-31 : true
2015-13-31 : true  <- 13 months??
2015-12-32 : true  <- 32 days??
1-1-1 : true

EXAMPLE with Kartic code:

String[] possibleDateFormats = new String[] { "yyyy", "yyyy-MM", "yyyy-MM-dd" };
String[] possibleDates = new String[] { "999", "1001", "2001", "1", "123-3", "1234-13", "2015-12-31", "2015-13-31", "2015-12-32", "1-1-1", "0-00-0" };

boolean isDate = false;

for ( String date : possibleDates )
{
    for ( String strDate : possibleDateFormats )
    {
        isDate = isValidDate( date, strDate );
        if ( isDate )
        {
            break;
        }
    }
    System.out.println(date + " :- " + isDate);
}

The output is the same...

Francesco
  • 2,350
  • 11
  • 36
  • 59
  • In the example code you posted, why are you calling setLenient(false)? I think that's wrong – ControlAltDel Sep 08 '15 at 14:50
  • A suggestion, put a `break;` after `isValid = true;` – Kartic Sep 08 '15 at 14:50
  • This has been asked before: See: [http://stackoverflow.com/questions/16014488/simpledateformat-parse-ignores-the-number-of-characters-in-pattern](http://stackoverflow.com/questions/16014488/simpledateformat-parse-ignores-the-number-of-characters-in-pattern) – Beowolve Sep 08 '15 at 14:59
  • 1
    Have you tried [Joda Time](http://stackoverflow.com/a/4330486/823393)? – OldCurmudgeon Sep 08 '15 at 14:59
  • `I tried with an example found in another thread, but it doesn't work` - Can you give us any example, where it is not working? – Kartic Sep 08 '15 at 15:14

3 Answers3

0

I couldn't think of any other options apart from what you have suggested.

I prefer the 1st option as it is simple and the date formats can be easily configured from external sources.

But, you need a small code change in order to make your code (1st option) to work perfectly. i.e., you are missing a break statement inside the for loop, if the date validation gets successful.

private boolean checkDateFormat( String dateString )
{
    String[] possibleDateFormats = new String[] { "yyyy", "yyyy-MM", "yyyy-MM-dd" };

    boolean isValid = false;

    for ( String possibleDateFormat : possibleDateFormats )
    {
        try
        {
            SimpleDateFormat simpleDateFormant = new SimpleDateFormat( possibleDateFormat );
            simpleDateFormant.setLenient( false );
            simpleDateFormant.parse( dateString.trim() );
            isValid = true;
            break;
        }
        catch ( ParseException pe )
        {
        }
    }

    return isValid;
}
Vasu
  • 21,832
  • 11
  • 51
  • 67
0

I have modified your code a little bit and tested it, working fine for me. Below is the updated code, can you give me an example where it is not working (other than date in some different format that the code is handling)

Method to check valid date

public static boolean isValidDate(final String strDate, final String dateFormat) {

    if (strDate == null || dateFormat == null) {
        return false;
    }

    SimpleDateFormat simpleDateFormant = new SimpleDateFormat(dateFormat);
    simpleDateFormant.setLenient(false);

    try {
        simpleDateFormant.parse(strDate.trim());
    } catch (ParseException e) {
        return false;
    }

    return true;
}

Test code

String[] possibleDateFormats = new String[] { "yyyy", "yyyy-MM", "yyyy-MM-dd" };
String inputDate = "1999";
boolean isDate = false;

for (String strDate : possibleDateFormats) {
    isDate = isValidDate(inputDate, strDate);
    if(isDate) {
        break;
    }
}

System.out.println(isDate);
Kartic
  • 2,935
  • 5
  • 22
  • 43
0

I tried with Joda Time and it works:

private static boolean checkDateFormat( String dateString ) 
    {
        String[] possibleDateFormats = new String[] { "yyyy-MM-dd", "yyyy-MM", "yyyy"  };

        boolean isValid = false;

        for ( String possibleDateFormat : possibleDateFormats )
        {
            try
            {
                DateTimeFormatter fmt = DateTimeFormat.forPattern(possibleDateFormat);
                fmt.parseDateTime(dateString.trim());

                isValid = true;
            }
            catch ( Exception e )
            {
            }
        }

        return isValid;
    }

OUTPUT:

999 : true
1001 : true
2001 : true
1 : true
123-3 : true
1234-13 : false
2015-12-31 : true
2015-13-31 : false
2015-12-32 : false
1-1-1 : true
123-4-5 : true
Francesco
  • 2,350
  • 11
  • 36
  • 59