<ctime> problema con le date di Febbraio

di il
5 risposte

<ctime> problema con le date di Febbraio

Salve ragazzi, sto scrivendo un programma in cui mi serve che venga calcolato il numero di giorni che intercorrono tra due date. Sto usando la libreria <ctime>, ma, effettuando vari controlli sul mio codice, ho notato che per i mesi di 30 giorni va tutto liscio, dato che inserendo ipoteticamente: 31/06/2013 e 01/07/2013 mi calcola 0 giorni, ma con il mese di Febbraio sorgono i problemi:
fino a 29 febbraio funziona bene (si accorge quando l'anno è bisestile o no) ma se disgraziatamente inserisco 30 o 31 febbraio, mi calcola i giorni come se esistessero realmente.
So che normalmente uno non inserirebbe mai queste date, ma penso che un codice ben fatto debba saper controllare qualsiasi situazione. Come posso risolvere? Pensavo di inserire un do-while per rieseguire il ciclo nel caso in cui una delle date sia 30 o 31 febbraio, ma mi sembra un po' macchinoso. Consigli?
#include <iostream>
#include <ctime>
#include <conio.h>
using namespace std;


int main() {
	static struct tm data1, data2;
    int g,m,a;
	
    
	do{printf("Inserisci prima data: ");
	scanf("%d/%d/%d", &g, &m, &a);
	data1.tm_mday = g; 
	data1.tm_mon = m - 1; 
	data1.tm_year = a - 1900; 

	printf("Inserisci seconda data: ");
	scanf("%d/%d/%d", &g, &m, &a);
	data2.tm_mday = g;
	data2.tm_mon = m - 1;
	data2.tm_year = a - 1900;

printf("La differenza tra le due date e' di %d giorni\n", abs(difftime(mktime(&data1), mktime(&data2))/86400));
cout<<"\n\nRieseguire?"; 
	}while(getch()!='n');
return 0;
}
L'output è questo
Inserisci prima data: 29/02/2013
Inserisci seconda data: 30/02/2013
La differenza tra le due date e' di 1 giorni


Rieseguire?Inserisci prima data: 29/02/2013
Inserisci seconda data: 31/02/2013
La differenza tra le due date e' di 2 giorni


Rieseguire?Inserisci prima data: 31/02/2013
Inserisci seconda data: 01/03/2013
La differenza tra le due date e' di 2 giorni


Rieseguire?

5 Risposte

  • Re: <ctime> problema con le date di Febbraio

    Per ora ho creato questa funzione qui
    bool febbraio(struct tm d1) {
    if(d1.tm_mday==30 && d1.tm_mon==1) return false;
    if(d1.tm_mday==31 && d1.tm_mon==1) return false;
    else return true;
    }
    e ho usato un ciclo do-while:
    do{
    //...inserisci prima data
    //...inserisci seconda data
    }while(!febbraio(data1) || !febbraio(data2));
    ma non sono convintissima
  • Re: <ctime> problema con le date di Febbraio

    Perche non usi difftime che ti dice il tempo trascorso tra una data e un altra invece di fare da sola i calcoli?

    http://www.cplusplus.com/reference/ctime/difftime
  • Re: <ctime> problema con le date di Febbraio

    Ma infatti l'ho usato difftime per calcolare i giorni tra una data e l'altra
    Il problema è che non ci sono controlli per i giorni che non esistono! quindi nel caso di febbraio, 30 e 31, ma nel caso degli altri mesi, da 31 in poi (mi sono resa conto ora a mente lucida).
    Vorrei che venisse impedito di inserire dei giorni che non esistono, tipo 30 febbraio o 32 gennaio
    Potrei ampliare la funzione che ho postato prima, facendo in modo che restituisca false ogni volta che la data supera l'ultimo giorno, ma, ripeto, lo trovo macchinoso e disordinato, perchè dovrei analizzare mese per mese. Come posso fare?
  • Re: <ctime> problema con le date di Febbraio

    Hai ragione non ho letto con attenzione.
    Se vuoi convalidare una data puoi partire da dei dati certi e cioè
    
    //vettore di giorni per mese
    int vett_giorni[] = {31,28,31,30,31,30,31,31,30,31,30,31};
    
    //vedi se l'anno è bisestile
    int annoBisestile( int year )
    {
    	return ((year % 4 == 0 && year % 100 != 0) || ( year % 400 == 0));
    }
    
    A sto punto puoi verificare date strane con
    if(giorno > vett_giorni[mese] && !annoBisestile(anno))
    // stampa data errata
    else if(annoBisestile(anno))
    {
        if(giorno == 29))
            //ok data giusta 29 febbraio in anno bisestile
    }
    else
    {
        // data giusta
    }
    Se non ho fatto errori dovrebbe essere giusta la convalida
  • Re: <ctime> problema con le date di Febbraio

    Ho notato che se l'anno è bisestile o no lo riconosce già, penso che dovrei per ogni mese fare in modo di non superare 30 o 31 a seconda dei casi (e nel caso di febbraio 29)

    ho fatto così e per ora sembra andare:
    #include <iostream>
    #include <ctime>
    #include <conio.h>
    using namespace std;
    struct tm;
    bool checkdata(struct tm, int);
    int main() {
    	static struct tm data1, data2;
        int g,m,a;
    	
        
    	do{
    		do{printf("Inserisci prima data: ");
    	scanf("%d/%d/%d", &g, &m, &a);
    	data1.tm_mday = g; 
    	data1.tm_mon = m - 1; 
    	data1.tm_year = a - 1900; 
        checkdata(data1, m-1);
    	printf("Inserisci seconda data: ");
    	scanf("%d/%d/%d", &g, &m, &a);
    	data2.tm_mday = g;
    	data2.tm_mon = m - 1;
    	data2.tm_year = a - 1900;
    	checkdata(data1, m-1);
    		}while(!checkdata(data1, m-1) || !checkdata(data2,m-1));
    printf("La differenza tra le due date e' di %d giorni\n", abs(difftime(mktime(&data1), mktime(&data2))/86400));
    cout<<"\n\nRieseguire?"; 
    	}while(getch()!='n');
    	cout<<"\n";
    return 0;
    }
    
    bool checkdata(struct tm d, int i) {
    int dpm[12]={31,29,31,30,31,30,31,31,30,31,30,31};
    if (d.tm_mday>dpm[i] && d.tm_mon==i) return false;
    else return true;
    }
Devi accedere o registrarti per scrivere nel forum
5 risposte