[supprimé]
Bonjour,
En Informatique on peut être amené à coder des dates. Le but est de les transformer en valeurs uniques de types entiers permettant des comparaisons rapides. Il est plus facile de faire une soustraction sur un entier que de manipuler le jour le mois et l'année pour y parvenir.
Une version assez simple pour le codage décodage peut être ainsi :
// déclaration globale à la classe
unsigned int dval ;
// transformation de l'entier dval en year, mounth, day
void parse_val( unsigned int & y, unsigned int & m , unsigned int & d )
{
y = ( dval >> 9 );
m = ( ( dval >> 5) & 15 ) ;
d = ( dval & 31 ) ;
}
// compacte année mois jour en entier dval
inline unsigned int pack_val( unsigned int y, unsigned int m , unsigned int d )
{
return d + (m << 5) + ( y << 9 ) ;
}
Ca marche mais il y a un problème. Par exemple si la date est 1990-01-01 on obtiendra une clé dval de valeur par exemple 3456666. Si on ajoute 1 jour on aura 3456667 soit +1. Par contre si on passe au mois suivant ou à l'année suivante il va y avoir une rupture dans la contiguité de la clé (dval). Certes c'est jouable tant que le veut pas faire de comparaisons ou de calcul d'intervalles. De plus on ne peut pas agir directement sur la clé puisque la contiguité ne respecte un pas d'incrémentation et de décrémentation unitaire.
Il existe donc une solution qui réalise l'exploit de coder de manière contigue toutes les dates valides. Une fois une date ainsi codée on peut agir directement sur la clé pour avancer ou reculer dans le temps. Mais cette solution est très difficile à mettre en oeuvre, je l'ai cueillie d'un autre programme et testé. Ainsi je vous la présente pour simple curiosité.
void parse_val( unsigned int & y, unsigned int & m, unsigned int & d )
{unsigned int d1;
unsigned int j1 = dval - 1721119L;
y = (unsigned int) (( ( j1 << 2) - 1) / 146097L);
j1 = ( j1 << 2 ) - 1 - 146097L * y;
d1 = ( j1 >> 2) ;
j1 = ( ( d1 << 2 ) + 3) / 1461;
d1 = ( d1 << 2 ) + 3 - 1461 * j1;
d1 = ( d1 + 4 ) >> 2;
m = (unsigned int) (5 * d1 - 3) / 153;
d1 = 5 * d1 - 3 - 153 * m;
d = (unsigned int)((d1 + 5)/5);
y = (unsigned int)(100 * y + j1);
if( m < 10 ) m += 3;
else
{
m -= 9;
++y;
}
}
unsigned int pack_val( unsigned int y, unsigned int m , unsigned int d )
{unsigned int c, ya;
if( y <= 99 ) y += 1900;
if( m > 2 ) m -= 3; else { m += 9; y--; }
c = y / 100;
ya = y - 100 * c;
return ( (146097L * c ) >> 2 ) + ((1461 * ya) >> 2 ) + (153 * m + 2) / 5 + d + 1721119L ;
}Comme on peut voir c'est assez élaboré, celui qui a fait cette implémentation a vraiment cerné le problème. On peut toutefois par ce mécanisme remonter dans le temps mais cela risque de ne plus avoir de sens si on obtient des dates antérieures au temps Grégorien. Je serais curieux de savoir comment on arrive à de tels calculs ?
Cordialement.