[RESOLVIDO] Problemas com validação de data

10 respostas
Onimatsu
Boa noite rapaziada. Estou tentando validar datas apartir de jformattedtextfield, por exemplo, se o usuário digitar 29/02/2009 era para retornar a mensagem "Data inválida" e o valor null porque esse ano é bissexto, só que ao invés disso retorna 01/03/2009 por causa do GregorianCalendar. O que eu preciso corrigir no código para que a data 29/02/2009 seja inválida e retorne null?
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
        GregorianCalendar gc = new GregorianCalendar();
        Date data = null;
        try {
            data = sdf.parse(txtDataNascimento.getText());
            gc.setTime(data);

            String vet[] = txtDataNascimento.getText().split("\\/");
            boolean is00dias = Integer.valueOf(vet[0]) == 0 || Integer.valueOf(vet[1]) == 0 || Integer.valueOf(vet[2]) == 0;
            boolean is28dias = (Integer.valueOf(vet[0]) >= 1 && Integer.valueOf(vet[0]) <= 28) && ((Integer.valueOf(vet[1]) - 1) == Calendar.FEBRUARY);
            boolean is29dias = (Integer.valueOf(vet[0]) >= 1 && Integer.valueOf(vet[0]) <= 29) && (((Integer.valueOf(vet[1]) - 1) == Calendar.FEBRUARY) && (gc.isLeapYear(Integer.valueOf(vet[2]))));
            boolean is30dias = (Integer.valueOf(vet[0]) >= 1 && Integer.valueOf(vet[0]) <= 30) && (((Integer.valueOf(vet[1]) - 1) == Calendar.APRIL) || ((Integer.valueOf(vet[1]) - 1) == Calendar.JUNE) || ((Integer.valueOf(vet[1]) - 1) == Calendar.SEPTEMBER) || ((Integer.valueOf(vet[1]) - 1) == Calendar.NOVEMBER));
            boolean is31dias = (Integer.valueOf(vet[0]) >= 1 && Integer.valueOf(vet[0]) <= 31) && (((Integer.valueOf(vet[1]) - 1) == Calendar.JANUARY) || ((Integer.valueOf(vet[1]) - 1) == Calendar.MARCH) || ((Integer.valueOf(vet[1]) - 1) == Calendar.MAY) || ((Integer.valueOf(vet[1]) - 1) == Calendar.JULY) || ((Integer.valueOf(vet[1]) - 1) == Calendar.AUGUST) || ((Integer.valueOf(vet[1]) - 1) == Calendar.OCTOBER) || ((Integer.valueOf(vet[1]) - 1) == Calendar.DECEMBER));

            if (is31dias || is30dias || is29dias || is28dias || !is00dias) {
//                System.out.println("data aceita");
                labelStatus.setForeground(Color.black);
                labelStatus.setText("");
                return data;
            } else {
//                System.out.println("data inválida");
                labelStatus.setForeground(Color.red);
                labelStatus.setText("Data inválida...");
                txtDataNascimento.setText(null);
                txtDataNascimento.setEnabled(true);
                data = null;
            }
        } catch (ParseException e) {
        } catch (Exception e) {
        }
        return null;

10 Respostas

E

Amigo, GregorianCalendar tem o metodo isLeapYear que verifica se o ano e bissexto, tente fazer assim:

public static boolean dataValida(String data) {

        int dia = new Integer(data.split("/")[0]);
        int mes = new Integer(data.split("/")[1]);
        int ano = new Integer(data.split("/")[2]);

        GregorianCalendar calendar = new GregorianCalendar();
        calendar.set(ano, mes, dia, 0, 0, 0);

        boolean isAnoBissexto = calendar.isLeapYear(ano);

        if (!isAnoBissexto && mes == 2 && dia > 28) {
            return false;
        } else {
            return true; 
        }

    }
pmlm

edulemos:
Amigo, GregorianCalendar tem o metodo isLeapYear que verifica se o ano e bissexto, tente fazer assim:

O problema não é só com o 29/02. Se colocares 32/03 automaticamente assume como 01/04.
A não ser que se use o método setLenient do DateFormat a false

String date = "29/02/2011";
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");

        try {
            Date d = sdf.parse(date);
            System.out.println(d);
        } catch (ParseException e) {
            System.out.println("Data inválida");
        }

        sdf.setLenient(false);

        try {
            Date d = sdf.parse(date);
            System.out.println(d);
        } catch (ParseException e) {
            System.out.println("Data inválida");
        }

O output do código acima é:

Tue Mar 01 00:00:00 GMT 2011
Data inválida
E

e só você fazer as validações que precisar:

public static boolean dataValida(String data) {

        int dia = new Integer(data.split("/")[0]);
        int mes = new Integer(data.split("/")[1]);
        int ano = new Integer(data.split("/")[2]);

        GregorianCalendar calendar = new GregorianCalendar();
        calendar.set(ano, mes, dia, 0, 0, 0);

        boolean isAnoBissexto = calendar.isLeapYear(ano);
                
        if( dia > 31 || mes > 12 ){
            return false;
        }else if (!isAnoBissexto && mes == 2 && dia > 28) {
            return false;
        } else {
            return true; 
        }

    }
sowyer

JodaTime não resolve ?

pmlm

edulemos:
e só você fazer as validações que precisar:

Para que reinventar a roda?

Onimatsu
Obrigado pessoal pela chuva de sugestões, mas acabei por encontrar a resposta neste site [url]http://stackoverflow.com/questions/8428313/simpledateformat-parsestring-str-didnt-been-throw-when-str-2011-12-12aaaaaa[/url] Segue o código para quem estiver com a mesma dificuldade :thumbup:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateValidCheck {


    public static void main(String[] args) {

        if(new DateValidCheck().isValidDate("2011/12/12aaa")){
            System.out.println("...date is valid");
        }else{
            System.out.println("...date is invalid...");
        }

    }


    public boolean isValidDate(String date) {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/d");
        Date testDate = null;
        try {
            testDate = sdf.parse(date);
        }
        catch (ParseException e) {
            return false;
        }
        if (!sdf.format(testDate).equals(date)) {
            return false;
        }
        return true;

    }
pmlm

Ao menos viste sequer o setLenient que eu falei?

Onimatsu

Sim, comprovei que o método setLenient funciona mas optei por usar outro código pela simplicidade em comparação ao código do meu primeiro post.
Obrigado pela dica.

pmlm
public boolean isValidDate(String date) {  
  
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/d");  
        Date testDate = null;  
        try {  
            testDate = sdf.parse(date);  
        }  
        catch (ParseException e) {  
            return false;  
        }  
        if (!sdf.format(testDate).equals(date)) {  
            return false;  
        }  
        return true;
Simplicidade??? Isto é simplicidade!
public boolean isValidDate(String date) {  
  
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/d");  
        sdf.setLenient(false)
        try {  
            sdf.parse(date);  
        }  
        catch (ParseException e) {  
            return false;  
        }  
        return true;
Onimatsu

Nessa perspectiva não discordo de você. :mrgreen:

Criado 11 de novembro de 2012
Ultima resposta 13 de nov. de 2012
Respostas 10
Participantes 4