Controlla se una stringa è una data valida in Java

1. Introduzione

In questo tutorial, discuteremo i vari modi per verificare se una stringa contiene una data valida in Java.

Discuteremo le soluzioni prima di Java 8, dopo Java 8 e utilizzando Apache Commons Validator.

2. Panoramica della convalida della data

Ogni volta che riceviamo dati in qualsiasi applicazione, dobbiamo verificarne la validità prima di eseguire qualsiasi ulteriore elaborazione.

Nel caso di input di data, potrebbe essere necessario verificare quanto segue:

  • L'input contiene la data in un formato valido, come MM / GG / AAAA
  • Le varie parti dell'input sono in un intervallo valido
  • L'input si risolve in una data valida nel calendario

Possiamo usare espressioni regolari per fare quanto sopra. Tuttavia, le espressioni regolari per gestire vari formati di input e impostazioni locali sono complesse e soggette a errori. Inoltre, possono ridurre le prestazioni.

Discuteremo i diversi modi per implementare le convalide della data in modo flessibile, solido ed efficiente.

Per prima cosa, scriviamo un'interfaccia per la convalida della data:

public interface DateValidator { boolean isValid(String dateStr); }

Nelle sezioni successive, implementeremo questa interfaccia utilizzando i vari approcci.

3. Convalidare utilizzando DateFormat

Java ha fornito funzionalità per formattare e analizzare le date sin dall'inizio. Questa funzionalità è nella classe astratta DateFormat e nella sua implementazione: SimpleDateFormat .

Implementiamo la convalida della data utilizzando il metodo di analisi della classe DateFormat :

public class DateValidatorUsingDateFormat implements DateValidator { private String dateFormat; public DateValidatorUsingDateFormat(String dateFormat) { this.dateFormat = dateFormat; } @Override public boolean isValid(String dateStr) { DateFormat sdf = new SimpleDateFormat(this.dateFormat); sdf.setLenient(false); try { sdf.parse(dateStr); } catch (ParseException e) { return false; } return true; } }

Poiché il DateFormat e classi correlate non sono thread-safe , stiamo creando una nuova istanza per ogni chiamata di metodo.

Quindi, scriviamo lo unit test per questa classe:

DateValidator validator = new DateValidatorUsingDateFormat("MM/dd/yyyy"); assertTrue(validator.isValid("02/28/2019")); assertFalse(validator.isValid("02/30/2019"));

Questa è stata la soluzione più comune prima di Java 8.

4. Convalida utilizzando LocalDate

Java 8 ha introdotto un'API di data e ora migliorata. Ha aggiunto la classe LocalDate , che rappresenta la data senza ora. Questa classe è immutabile e thread-safe.

LocalDate fornisce due metodi statici per analizzare le date. Entrambi usano un DateTimeFormatter per eseguire l'analisi effettiva:

public static LocalDate parse​(CharSequence text) // parses dates using using DateTimeFormatter.ISO_LOCAL_DATE public static LocalDate parse​(CharSequence text, DateTimeFormatter formatter) // parses dates using the provided formatter

Usiamo il metodo di analisi per implementare la convalida della data:

public class DateValidatorUsingLocalDate implements DateValidator { private DateTimeFormatter dateFormatter; public DateValidatorUsingLocalDate(DateTimeFormatter dateFormatter) { this.dateFormatter = dateFormatter; } @Override public boolean isValid(String dateStr) { try { LocalDate.parse(dateStr, this.dateFormatter); } catch (DateTimeParseException e) { return false; } return true; } }

L'implementazione utilizza un oggetto DateTimeFormatter per la formattazione. Poiché questa classe è thread-safe, utilizziamo la stessa istanza in diverse chiamate di metodo.

Aggiungiamo anche uno unit test per questa implementazione:

DateTimeFormatter dateFormatter = DateTimeFormatter.BASIC_ISO_DATE; DateValidator validator = new DateValidatorUsingLocalDate(dateFormatter); assertTrue(validator.isValid("20190228")); assertFalse(validator.isValid("20190230"));

5. Convalidare utilizzando DateTimeFormatter

Nella sezione precedente, abbiamo visto che LocalDate utilizza un oggetto DateTimeFormatter per l'analisi. Possiamo anche usare direttamente la classe DateTimeFormatter per la formattazione e l'analisi.

DateTimeFormatter analizza un testo in due fasi. Nella fase 1, analizza il testo in vari campi di data e ora in base alla configurazione. Nella fase 2, risolve i campi analizzati in un oggetto data e / o ora.

L' attributo ResolverStyle controlla la fase 2. È un'enumerazione con tre possibili valori:

  • LENIENTE - risolve date e orari con indulgenza
  • SMART: risolve date e orari in modo intelligente
  • RIGOROSO - risolve rigorosamente date e orari

Ora scriviamo la convalida della data usando direttamente DateTimeFormatter :

public class DateValidatorUsingDateTimeFormatter implements DateValidator { private DateTimeFormatter dateFormatter; public DateValidatorUsingDateTimeFormatter(DateTimeFormatter dateFormatter) { this.dateFormatter = dateFormatter; } @Override public boolean isValid(String dateStr) { try { this.dateFormatter.parse(dateStr); } catch (DateTimeParseException e) { return false; } return true; } }

Successivamente, aggiungiamo lo unit test per questa classe:

DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd", Locale.US) .withResolverStyle(ResolverStyle.STRICT); DateValidator validator = new DateValidatorUsingDateTimeFormatter(dateFormatter); assertTrue(validator.isValid("2019-02-28")); assertFalse(validator.isValid("2019-02-30"));

Nel test precedente, stiamo creando un DateTimeFormatter basato su pattern e impostazioni locali. Stiamo usando la risoluzione rigorosa per le date.

6. Convalidare utilizzando Apache Commons Validator

Il progetto Apache Commons fornisce un framework di convalida. Contiene routine di convalida, come data, ora, numeri, valuta, indirizzo IP, e-mail e URL.

Per il nostro obiettivo in questo articolo, diamo un'occhiata alla classe GenericValidator , che fornisce un paio di metodi per verificare se una stringa contiene una data valida:

public static boolean isDate(String value, Locale locale) public static boolean isDate(String value,String datePattern, boolean strict)

Per utilizzare la libreria, aggiungiamo la dipendenza Maven del validatore dei comuni al nostro progetto:

 commons-validator commons-validator 1.6 

Successivamente, usiamo la classe GenericValidator per convalidare le date:

assertTrue(GenericValidator.isDate("2019-02-28", "yyyy-MM-dd", true)); assertFalse(GenericValidator.isDate("2019-02-29", "yyyy-MM-dd", true));

7. Conclusione

In questo articolo, abbiamo esaminato i vari modi per verificare se una stringa contiene una data valida.

Come al solito, il codice sorgente completo può essere trovato su GitHub.