2

Im trying to achive this: I have a method that recieves a string that is the format of a date pattern (example "dd/mm/yyyy") and the method has to validate if the pattern is valid in java or not. Example, lets say I have the following input:

String input1="dd/mm/yyyy";
String input2="mm/dd/yyyy";
String input3"cceq.der.sads";
String input4= "dd-M-yyyy hh:mm:ss"

public Boolean validPatternDate(String in){
//The code im looking for
}

The result of each input being applied to the validPatternDate method is going to be:

input1 True
input2 True
input3 False
input4 True

Is there a way of doing this in java? Thanks

rolo
  • 473
  • 1
  • 5
  • 16
  • Considering *you* need to define what patterns your consider valid, see [here](https://stackoverflow.com/a/43692146/133203). – Federico klez Culloca Jul 12 '21 at 19:19
  • did you try to instanciate a simpledateformat or a DateTimeFormatter object with the pattern? – njzk2 Jul 12 '21 at 19:19
  • Thanks for answering. What is the result of instanciate a simpledateformat with a wrong pattern? an exception? – rolo Jul 12 '21 at 19:24
  • 2
    If you use [SimpleDateFormat#parse](https://docs.oracle.com/javase/10/docs/api/java/text/SimpleDateFormat.html#parse(java.lang.String,java.text.ParsePosition)), it should return `null` for errors. – dan1st Jul 12 '21 at 19:58
  • Look [here](https://stackoverflow.com/questions/20231539/java-check-the-date-format-of-current-string-is-according-to-required-format-or/20232680). It should answer you question. – Paweł Lenczewski Jul 12 '21 at 20:51
  • 2
    @njzk2 and others, I recommend you never use `SimpleDateFormat`. That class is notoriously troublesome and long outdated. Instead use `DateTimeFormatter` from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Jul 13 '21 at 04:42

2 Answers2

2

tl;dr

Try DateTimeFormatter.ofPattern while trapping for IllegalArgumentException.

try {
    formatter = DateTimeFormatter.ofPattern( input ) ;
} catch ( IllegalArgumentException e ) {
    … // Handle exception thrown for invalid input formatting pattern.
}

Better yet, let DateTimeFormatter.ofLocalized… automatically localize instead of you trying to allow troublesome arbitrary format strings.

Localize, instead

Accepting any arbitrary formatting pattern is going to be a problematic headache. Formatting patterns are complicated and subtle.

In addition, many of the formats will require that you also specify a Locale to determine the human language and cultural norms necessary to decide issues such as translation of month name & day-of-week name & so on, abbreviation, capitalization, punctuation, and more.

I suggest you instead let java.time localize. Instead of passing a formatting pattern, you would pass a FormatStyle enum object (or string of its name), and a Locale object. But as I mentioned above, you need to pass a Locale in any event.

Use the FormatStyle and Locale to get a localizing DateTimeFormatter object.

FormatStyle style = FormatStyle.MEDIUM ;
Locale locale = Locale.CANADA_FRENCH ;

DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDate( style ).withLocale( locale ) ;
LocalDate localDate = LocalDate.now( ZoneId.of( "Africa/Tunis" ) ) ;
String output = localDate.format( formatter ) ;

See this code run live at IdeOne.com.

12 juill. 2021

Trap IllegalArgumentException

If you insist on your approach of accepting arbitrary formatting patterns, you can attempt to use that format with DateTimeFormatter class. Call its ofPattern method. Trap for the IllegalArgumentException thrown if the pattern is invalid.

String input = "dd/mm/yyyy" ;
DateTimeFormatter f = null ;
try {
    formatter = DateTimeFormatter.ofPattern( input ) ;
} catch ( IllegalArgumentException e ) {
    … // Handle exception thrown for invalid input formatting pattern.
}

Beware: As mentioned above, some formats require a Locale. So you should be receiving a locale argument as well as a formatting pattern, and calling DateTimeFormatter.withLocale.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
2

Basil Bourque has already given the good answer. I wanted to add a modest supplement.

All of your input patterns are incorrect

It appears to me that none of your patterns input1 through input4 is correct! You are using almost only lower case letters in your patterns. Format patterns are case sensitive, and I am convinced that you wanted to use some upper case letters for some of the letters. For example dd/MM/yyyy could be a valid pattern for day, month and year separated by slashes. Your input1, dd/mm/yyyy is not. And the code by Basil Bourque does not catch this error since lower case m is a valid pattern letter — for minute of hour (your are using both M and mm correctly in your input4).

You may attempt to catch some of such errors by parsing or formatting using the formatter that you get from DateTimeFormatter.ofPattern(). The challenge is which string to parse, which date-time type to parse it into (which can be essential) or which date-time type to format. Without this knowledge it is not going to work.

Catching all errors is not realistic

On the curious side DateTimeFormatter.ofPattern() will let patterns through that in a human eye are clearly meaningless because pretty many pattern letters are valid. For example:

    String input = "MAD way";
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(input);
    System.out.println(formatter.format(LocalDateTime.now(ZoneId.systemDefault())));

Output:

786390607193 28PM2021

There is realistically nothing you can do about this, and it is very unlikely to be a problem in practice.

Do not return an object

Don’t return a Boolean object. What would null signify here? Return a primitive boolean so the caller knows that the result is always either false or true.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161