[C++] Verificar se uma data é válida

OubeLa

Power Member
NOTA: não me responsabilizo por qualquer bug presente nos seguintes excertos de código.

Criei uma classe Data para representar datas (dias, mes, ano). Depois, criei também duas funções que em conjunto verificam se uma data é válida. Quando fiz isto era menos experiente do que sou agora, portanto é natural que algumas coisas pudessem ser melhoradas.


Primeiro criei a classe Data

Data.h
Código:
#ifndef DATA_H_
#define DATA_H_

class Data
{

    unsigned int dia; //dia de uma Data
    unsigned int mes; //mes de uma Data
    unsigned int ano; //ano de uma Data

public:
    Data(unsigned int, unsigned int, unsigned int);
    void setDia(unsigned int);
    unsigned int getDia() const;
    void setMes(unsigned int);
    unsigned int getMes() const;
    void setAno(unsigned int);
    unsigned int getAno() const;
    void mostraData() const;
};

#endif /*DATA_H_*/
Data.cpp
Código:
#include "Data.h"

#include <iostream>

using namespace std;

//construtor da classe Data
Data::Data(unsigned int d, unsigned int m, unsigned int a)
{
    setDia(d);
    setMes(m);
    setAno(a);
}

void Data::setDia(unsigned int d)
{
    dia = d;
}

unsigned int Data::getDia() const
{
    return dia;
}

void Data::setMes(unsigned int m)
{
    mes = m;
}

unsigned int Data::getMes() const
{
    return mes;
}

void Data::setAno(unsigned int a)
{
    ano = a;
}

unsigned int Data::getAno() const
{
    return ano;
}

void Data::mostraData() const
{
    cout << "     " << dia << " / " << mes << " / " << ano << endl;
}
Função que verifica se um determinado ano é bissexto.

Código:
//verifica se um ano é bissexto. Retorna true se for bissexto, false se não for
bool anoBissexto(Data data)
{
    bool bi = false;

    if (data.getAno() % 400 == 0 || data.getAno() % 4 == 0 && data.getAno() % 100 != 0)
        bi = true;

    return bi;
}
Função que verifica se uma determinada data é válida (verifica meses com 28, 29, 30 e 31 dias e anos bissextos).

Código:
bool dataValida(Data data)
{
    bool dValida = false;
    
    //ano tem de ser maior que 0
    if (data.getAno() > 0)
    {
        if (data.getMes() > 0 && data.getMes() <= 12)
        {
            if (data.getMes() == 1 || data.getMes() == 3 || data.getMes() == 5 || data.getMes() == 7 || data.getMes() == 8 || data.getMes() == 10 || data.getMes() == 12)
            {
                if (data.getDia() > 0 && data.getDia() <= 31)
                    dValida = true;
            }

            else if (data.getMes() == 4 || data.getMes() == 6 || data.getMes() == 9 || data.getMes() == 11)
            {
                if (data.getDia() > 0 && data.getDia() <= 30)
                    dValida = true;
            }

            else if (data.getMes() == 2)
            {
                if (anoBissexto(data) == false)
                {
                    if (data.getDia() > 0 && data.getDia() <= 28)
                        dValida = true;
                }

                //se o ano for bissexto, o mes de Fevereiro pode ter 29 dias
                else if (anoBissexto(data) == true)
                {
                    if (data.getDia() > 0 && data.getDia() <= 29)
                        dValida = true;
                }
            }
        }
    }
    return dValida;
}
Cumprimentos
 
Partindo do pressuposto que não existem datas inválidas

deverás ter essa função dataValida() como private e com o nome cumpreInvariante()

e chamá-la no construtor desta forma, por exemplo.

Código:
Data::Data(unsigned int d, unsigned int m, unsigned int a)
{
    setDia(d);
    setMes(m);
    setAno(a);
    assert(cumpreInvariante());
}

era o que eu faria.

Cumprimentos
 
Código:
     #region [valida datas]

                    /*************Datas**********/
                    /*validacao de comparação entre duas datas ,
                     * datai - datainicial, 
                     * dataf - datafinal, 
                     * label - label erro da data final*/
                    public bool [COLOR=Orange][B]comparadatas[/B][/COLOR](DateTime datai, DateTime dataf, System.Web.UI.WebControls.Label label)
                    {
                      bool res = false;
                      if (dataf >= datai)
                      {
                        res = true;
                        label.Text = "<span class=\"erroverdade\">*</span> ";
                      }
                      else
                      {
                        res = false;
                        label.Text = "<span class=\"errofalso\">*</span> ";
                      }
                      return res;
                    } 

                    /*Validação geral d um campo data  */
                    /* data - string da data inserida na textbox
                     * dataminima - string da data minima que pode ser inserida
                     * label - id da labelde erro referente a um determinado campo */
                    public bool [B][COLOR=Orange]VDatas[/COLOR][/B](string data, string dataminima, System.Web.UI.WebControls.Label label)
                    {

                      bool resul = false;

                      // testa para caixa de data decisão vazia
                      if (data == "")
                      {
                        label.Text = "<span class=\"errofalso\">*</span> ";

                        resul = false;
                      }
                      // valida campo diferente de vazio
                      if (data != "")
                      {
                        //valida para campo com 10 caracteres e campo com tim e 10 caracteres
                        if ((data.Length == 10) || (data.Length == 10))// testa p numero de caracteres
                        {
                          // testa se e data valida
                          if (validaData(data))
                          {
                            string datamin = dataminima;
                            string strdatamin = datamin.Substring(6, 4) + "-" + datamin.Substring(3, 2) + "-" + datamin.Substring(0, 2);
                            DateTime datageral2 = Convert.ToDateTime(strdatamin);

                            string str = data.Substring(6, 4) + "-" + data.Substring(3, 2) + "-" + data.Substring(0, 2);
                            DateTime datageral = Convert.ToDateTime(str);

                            //testa se é menor ou igual que  a data actual
                            if (datageral <= datageral2)
                            {
                              label.Text = "<span class=\"errofalso\">*</span>";
                              resul = false;
                            }
                            //testa se é maior que a data actual
                            if (datageral > datageral2)
                            {
                              label.Text = "<span class=\"erroverdade\">*</span>";
                              resul = true;
                            }

                          }
                          else
                          {
                            label.Text = "<span class=\"errofalso\">*</span>";

                            resul = false;
                          }
                        }
                        else
                        {
                          label.Text = "<span class=\"errofalso\">*</span>";

                          resul = false;

                        }

                      }
                      return resul;
                    }

                    //valida data no ambito da sua formatação
                    private bool [B][COLOR=Orange]validaData[/COLOR][/B](string str)
                    {

                      Regex Data = new Regex(@"^((((0?[1-9]|[12]\d|3[01])[\-](0?[13578]|1[02])[\-]((1[6-9]|[2-9]\d)?\d{2}))|((0?[1-9]|[12]\d|30)[\-](0?[13456789]|1[012])[\-]((1[6-9]|[2-9]\d)?\d{2}))|((0?[1-9]|1\d|2[0-8])[\-]0?2[\-]((1[6-9]|[2-9]\d)?\d{2}))|(29[\-]0?2[\-]((1[6-9]|[2-9]\d)?(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00)|00)))|(((0[1-9]|[12]\d|3[01])(0[13578]|1[02])((1[6-9]|[2-9]\d)?\d{2}))|((0[1-9]|[12]\d|30)(0[13456789]|1[012])((1[6-9]|[2-9]\d)?\d{2}))|((0[1-9]|1\d|2[0-8])02((1[6-9]|[2-9]\d)?\d{2}))|(2902((1[6-9]|[2-9]\d)?(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00)|00))))$");
                      return Data.IsMatch(str);

                    }




            #endregion
tens ai um conjunto de metodos em c# desenvolvidos por mim , excepto a exp regular

validaData() , verifica tb se ano é bisexto ou n , recebe uma string data e verifica se a mesma é valida em ralaç
ão a uma especificação, penso que esta formatada para dd-mm-aaaa, sempre a podes alterar
devolvendo true caso seja valida e false caso contrario


comparadatas(), compara se uma data é maior que outra devolvendo true caso verdade e false caso falso ....


VDatas() tb devolve true ou false caso seja verdadeiro ou falso.

esta faz tdas as verificações possiveis (pode falgar uma ou outra mas são suficientes),

  • se o campo de data vazio ou não ,
  • verifica o tamanho da string da data,
  • se data valida "validaData()",
  • verifica se a data a tua data em relação a actual.

como não estou habituado a c++ pensei que isto em c# te ia dar uma ajuda

bom trabalho
 
Última edição:
alfinete: agradecia que, se pudesses, criasses um novo tópico de forma a este ser adicionado ao repositório de código. Depois, coloca aqui o tópico para ele ser adicionado ao repositório.
 
Back
Topo