Verifique se uma string é uma data válida em Java
1. Introdução
Neste tutorial, discutiremos as várias maneiras de verificar seString contém uma data válida em Java.
Discutiremos as soluções antes do Java 8, depois do Java 8 e usando oApache Commons Validator.
2. Visão geral da validação de data
Sempre que recebemos dados em qualquer aplicativo, precisamos verificar se são válidos antes de fazer qualquer processamento adicional.
No caso de entradas de data, talvez seja necessário verificar o seguinte:
-
A entrada contém a data em um formato válido, como MM / DD / AAAA
-
As várias partes da entrada estão em um intervalo válido
-
A entrada é resolvida para uma data válida no calendário
Podemos usarregular expressions para fazer o acima. No entanto, expressões regulares para lidar com vários formatos e localidades de entrada são complexas e propensas a erros. Além disso, eles podem prejudicar o desempenho.
Discutiremos as diferentes maneiras de implementar validações de data de maneira flexível, robusta e eficiente.
Primeiro, vamos escrever uma interface para a validação de data:
public interface DateValidator {
boolean isValid(String dateStr);
}
Nas próximas seções, implementaremos essa interface usando as várias abordagens.
3. Validar usandoDateFormat
Java forneceu recursos para formatar e analisar datas desde o início. Esta funcionalidade está na classeDateFormat abstract e sua implementação -SimpleDateFormat.
Vamos implementar a validação de data usando o métodoparse da classeDateFormat:
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;
}
}
Comothe DateFormat and related classes are not thread-safe, estamos criando uma nova instância para cada chamada de método.
A seguir, vamos escrever o teste de unidade para esta classe:
DateValidator validator = new DateValidatorUsingDateFormat("MM/dd/yyyy");
assertTrue(validator.isValid("02/28/2019"));
assertFalse(validator.isValid("02/30/2019"));
Essa foi a solução mais comum antes do Java 8.
4. Validar usandoLocalDate
Java 8 introduziu umimproved Date and Time API. Ele adicionou oLocalDate class, which represents the date without time. This class is immutable and thread-safe.
LocalDate fornece dois métodos estáticos para analisar datas. Ambos usamDateTimeFormatter para fazer a análise real:
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
Vamos usar o métodoparse para implementar a validação de 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;
}
}
A implementação usa um objetoDateTimeFormatter para formatação. Como essa classe é thread-safe, estamos usando a mesma instância em diferentes chamadas de método.
Vamos também adicionar um teste de unidade para esta implementação:
DateTimeFormatter dateFormatter = DateTimeFormatter.BASIC_ISO_DATE;
DateValidator validator = new DateValidatorUsingLocalDate(dateFormatter);
assertTrue(validator.isValid("20190228"));
assertFalse(validator.isValid("20190230"));
5. Validar usandoDateTimeFormatter
Na seção anterior, vimos queLocalDate usa um objetoDateTimeFormatter para análise. Também podemos usar a classeDateTimeFormatter diretamente para formatação e análise.
DateTimeFormatter parses a text in two phases. Na Fase 1, ele analisa o texto em vários campos de data e hora com base na configuração. Na fase 2, ele resolve os campos analisados em um objeto de data e / ou hora.
O atributoResolverStyle controla a fase 2. É umenum com três valores possíveis:
-
LENIENT - resolve datas e horas de forma branda
-
SMART - resolve datas e horas de maneira inteligente
-
STRICT - resolve estritamente datas e horários
Agora, vamos escrever a validação de data usandoDateTimeFormatter diretamente:
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;
}
}
A seguir, vamos adicionar o teste de unidade para esta 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"));
No teste acima, estamos criando umDateTimeFormatter com base no padrão e localidade. Estamos usando a estrita resolução para datas.
6. Validar usando o Apache Commons Validator
O projetoApache Commons fornece uma estrutura de validação. This contains validation routines, such as date, time, numbers, currency, IP address, email, and URL.
Para nosso objetivo neste artigo, vamos dar uma olhada na classeGenericValidator, que fornece alguns métodos para verificar se umString contém uma data válida:
public static boolean isDate(String value, Locale locale)
public static boolean isDate(String value,String datePattern, boolean strict)
Para usar a biblioteca, vamos adicionar a dependência Mavencommons-validator ao nosso projeto:
commons-validator
commons-validator
1.6
A seguir, vamos usar a classeGenericValidator para validar as datas:
assertTrue(GenericValidator.isDate("2019-02-28", "yyyy-MM-dd", true));
assertFalse(GenericValidator.isDate("2019-02-29", "yyyy-MM-dd", true));
7. Conclusão
Neste artigo, examinamos as várias maneiras de verificar seString contém uma data válida.
Como de costume, o código-fonte completo pode ser encontradoover on GitHub.