Bibliothèque Date en C

Fermé
rafale69300 Messages postés 84 Date d'inscription vendredi 31 octobre 2008 Statut Membre Dernière intervention 15 juin 2010 - 24 mars 2009 à 17:37
mamiemando Messages postés 33459 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 8 janvier 2025 - 24 mars 2009 à 20:23
Bonjour, voici mon petit problème :
J'ai construit une librairie date, et j'ai un petit problème au niveau de la fonction nombre de jours entre 2 date. Comme vous pourrez le voir cette fonction appelle calcul même année c'est à dire le nombre de jours entre 2 dates de même année et elle appelle aussi calcul année différente c'est à dire le nombre de jours entre 2 dates d'année différentes. Et je pense que mon problème vient de cette fonction car quand je rentre 2 dates d'année différentes, j'ai un jour d'écart avec mon jeu d'essai ( fait à l'aide d'excel) ou si je met un écart d'un siècle là l'écart est plus important, il est de 49 jours. Donc si vous pouviez m'aider, je mets à votre disposition mon .h et .c
Merci d'avance pour votre aide.

Date.h

typedef struct{
	int j,m,a;
}DATE;

typedef enum {faux,vrai}BOOLEEN;

/*Permet de saisir une date*/
void saisir (DATE *d);

/*Construit une date, à partir des paramètres passés*/
DATE construire(int jour, int mois, int an);

/*Construit une date, retourne la date du jour*/
DATE construire_datejour(void);

/*Retourne le jour de la date passée en paramètre*/
int get_jour(DATE d);

/*Retourne le mois de la date passée en paramètre*/
int get_mois(DATE d);

/*Retourne l'année de la date passée en paramètre*/
int get_an(DATE d);

/*Affiche la date passée en paramètre*/
void afficher(DATE d);

/*Retourne vrai si d1 est avant d2, faux dans le cas contraire*/
BOOLEEN est_avant(DATE d1, DATE d2);

/*Retourne vrai si l'année est bissextile, faux dans le cas contraire*/
BOOLEEN est_bissextile(int an);

/*Retourne vrai si la date passée en paramètre est valide, faux dans le cas contraire*/
BOOLEEN controle_date(DATE d);

/*Ajoute n jours à la date d passée en paramètre et retourne la nouvelle date*/
DATE ajouter_nbj(DATE d, int n);

/*Calcule le nb de jours écoulés entre les 2 dates d1 et d2, retourne ce nombre*/
int nbj_deuxdates(DATE d1,DATE d2);

/*Initialise le tableau Tmois ; ici, Février a 28 jours*/
void init_mois(int Tmois[]);

/*Fonctions appelées par nbj_deuxdates*/

/*calcule le nombre de jours écoulés entre deux dates de meme année*/
int calcul_meme_annee(DATE d1, DATE d2, int Tmois[]);

/*calcule le nombre de jours écoulés entre deux dates d'année différente*/
int calcul_annee_differente(DATE d1, DATE d2, int Tmois[]);

/*Cumule les jours écoulés entre m1 et m2 (mois pleins)*/
int calcul_mois_plein(int m1, int m2, int a, int Tmois[]);


Date.c

#include<stdlib.h>
#include<stdio.h>
#include"date.h"


void saisir(DATE *d) /*Permets de saisir une date*/
{
	int j,m,a;
	printf("\nSaisir jour");
	scanf("%d",&j);
	d->j = j;
	printf("\nSaisir mois");
	scanf("%d",&m);
	d->m = m;
	printf("\nSaisir an");
	scanf("%d",&a);
	d->a = a;
}

DATE construire(int jour,int mois,int an)
/*Construire une date, à partir des paramètres passés*/
{
	DATE LaDate;
	LaDate.j = jour;
	LaDate.m = mois;
	LaDate.a = an;
	return LaDate;
}

DATE construire_datejour(void)
/*Construit une date, retourne la date du jour*/
{
	
}

int get_jour(DATE d)
/*Retourne le jour de la date passée en paramètre*/
{
	return d.j;
}

int get_mois(DATE d)
/*Retourne le mois de la date passée en paramètre*/
{
	return d.m;
}

int get_an(DATE d)
/*Retourne l'année de la date passée en paramètre*/
{
	return d.a;
}

void afficher(DATE d)
/*Affiche la date passée en paramètre*/
{	
	printf("\n%d/%d/%d",d.j,d.m,d.a);
}

BOOLEEN est_avant(DATE d1, DATE d2)
/*Retourne vrai si d1 est avant d2, faux dans le cas contraire*/
{
	BOOLEEN avant;
	avant = faux;
	if(d1.a < d2.a){
		avant = vrai;
	}	
	else if(d1.m < d2.m && d1.a == d2.a){
		avant = vrai;
	}
	else if(d1.j < d2.j && d1.m == d2.m){
		avant = vrai;
	}
	return avant;
}

BOOLEEN est_bissextile(int an)
/*Retourne vrai si l'année est bissextile, faux dans le cas contraire*/
{
	BOOLEEN biss;
	if(an%400 == 0 || (an%4 == 0 && an%100 != 0)){
		biss = vrai;
	}	
	else
		biss = faux;
	return biss;
}

BOOLEEN controle_date(DATE d)
/*Retourne vrai si la date passée en paramètre est valide, faux dans le cas contraire*/
{
	BOOLEEN valide;
	valide = vrai;
	if(d.j < 1 || d.j > 31 || d.m < 1 || d.m > 12){
		valide = faux;
	}
	else if(d.m == 4 || d.m == 6 || d.m == 9 || d.m == 11){
		if(d.j == 31){
			valide = faux;
		}
	else if(d.m == 2){
		if(d.j > 29){
			valide = faux;
		}
		else if(!est_bissextile(d.a) && d.j == 29){
			valide = faux;
		}
	}
	}
	return valide;
}

int nbj_deuxdates(DATE d1,DATE d2)
/*Calcule le nb de jours écoulés entre les 2 dates d1 et d2, retourne ce nombre*/
{
	int n;
	int Tmois[11];
	init_mois(Tmois);
   	if(d1.a == d2.a) 
       		n = calcul_meme_annee(d1,d2,Tmois);
   	else 
        	n = calcul_annee_differente(d1,d2,Tmois);
       	return n;
}

void init_mois(int Tmois[])
/*Initialise le tableau Tmois ; ici, Février a 28 jours*/
{
	Tmois[0] = 31;
	Tmois[1] = 28;
	Tmois[2] = 31;
	Tmois[3] = 30;
	Tmois[4] = 31;
	Tmois[5] = 30;
	Tmois[6] = 31;
	Tmois[7] = 31;
	Tmois[8] = 30;
	Tmois[9] = 31;
	Tmois[10] = 30;
	Tmois[11] = 31;
}

/*Fonctions appelées par nbj_deuxdates*/
	
int calcul_meme_annee(DATE d1, DATE d2, int Tmois[])
/*calcule le nombre de jours écoulés entre deux dates de meme année*/
{
	int n;
    if(est_bissextile(d1.a)) {
        Tmois[1] = 29;
    } else {
        Tmois[1] = 28;
    }
    n = 0;
    if(d1.m == d2.m) {
        if(est_avant(d1,d2)) {
            return d2.j - d1.j;
        } else {
            return d1.j - d2.j;
        }
    } else {
        if(est_avant(d1,d2)) {
            n = calcul_mois_plein(d1.m,d2.m,d1.a,Tmois) + d2.j + (Tmois[d1.m - 1] - d1.j);
        } else {
            n = calcul_mois_plein(d2.m,d1.m,d1.a,Tmois) + d2.j + (Tmois[d1.m - 1] - d1.j);
        }
    }
    return n;
}

int calcul_annee_differente(DATE d1, DATE d2, int Tmois[])
/*calcule le nombre de jours écoulés entre deux dates d'année différente*/
{
	int n, cptan, cptanfin;
    if(est_avant(d1,d2)) {
        cptan = d1.a + 1;
        cptanfin = d2.a - 1;
    } else {
        cptan = d2.a + 1;
        cptanfin = d1.a - 1;
    }
    n = 0;
    while(cptan <= cptanfin) {
        if(est_bissextile(cptan)) {
            n+= 365;
        } else {
            n+= 366;
        }
        cptan++;
    }

    if(est_avant(d1,d2)) {
        n += calcul_meme_annee(construire(1,1,d2.a),d2,Tmois) + calcul_meme_annee(d1,construire(31,12,d1.a),Tmois);
    } else {
        n += calcul_meme_annee(construire(1,1,d1.a),d1,Tmois) + calcul_meme_annee(d2,construire(31,12,d2.a),Tmois);
    }
    return n;
}

int calcul_mois_plein(int m1, int m2, int a, int Tmois[])
/*Cumule les jours écoulés entre m1 et m2 (mois pleins)*/
{
	int debut,fin,n;
	n = 0;
    if(m1 == m2) return 0;
    else {
        if(est_bissextile(a)) {
            Tmois[1] = 29;
        } else {
            Tmois[1] = 28;
        }
        if(m1 > m2) {
            debut = m2+1;
            fin = m1-1;
        } else {
            debut = m1+1;
            fin = m2-1;
        }
        for(debut; debut <= fin; debut++) {
            n+= Tmois[debut-1];
        }
        return n;
    }
}

2 réponses

rafale69300 Messages postés 84 Date d'inscription vendredi 31 octobre 2008 Statut Membre Dernière intervention 15 juin 2010 2
24 mars 2009 à 19:50
Snif j'ai pas d'aide...
0
mamiemando Messages postés 33459 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 8 janvier 2025 7 813
24 mars 2009 à 20:23
En fait tu t'es un peu cassé la tête pour rien, tu aurais dû utiliser directement un timestamp.
http://fr.wikipedia.org/wiki/Timestamp_(informatique)

En d'autres termes, une date est simplement stockée sous forme d'un entier qui donne le nombre de seconde écoulées depuis une date origine (le plus souvent le 1er janvier 1970 à minuit). Rien ne t'empêche de faire un timestamp basé sur des jours si tu veux couvrir une plage de temps plus importante. Toutefois avec un timestamp en seconde et basé sur le 1er janvier 1970, il existe plein de fonctions pour remettre en forme facilement une date dans la librairie standard. Voir par exemple :
http://www.linux-kheops.com/doc/man/manfr/man-html-0.9/man2/time.2.html
http://www.linux-kheops.com/doc/man/manfr/man-html-0.9/man3/ctime.3.html

Revenons à ta librairie. Si on reste sur ta structure, la manière la plus simple de t'en sortir est de repasser par un "struct tm" (voir second lien), de les convertir en time_t (avec la fonction mktime), de faire la différence. Ensuite une division entière par 60*60*24 te donnera le nombre de jour écoulés entre les deux dates.

Si tu ne passes pas par un timestamp, tu vas galérer avec les années bissextiles, etc...

Bonne chance
0