Coder une datetime de 14 caractères en 5 caractères

Coder une datetime de 14 caractères en 5 caractères - Algo - Programmation

Marsh Posté le 14-04-2004 à 12:12:34    

Salut,
 
J'ai une chaine datetime du type  
AAAAMMDDHHMMSS
20040314121025
 
et j'aimerais coder ça sur seulement 5 caractères alphanumérique (lettres majuscules et chiffres seulement)
 
Si c'est possible, comment faire ?  
(éventuellement en supprimant les 4 chiffres de l'année et même les deux du mois)
 
Merci A+
 
Si vous avez une fonction toute faite (en C) je suis preneur :)


Message édité par Eniac le 14-04-2004 à 16:26:33
Reply

Marsh Posté le 14-04-2004 à 12:12:34   

Reply

Marsh Posté le 14-04-2004 à 13:07:49    

pas possible.  
 
Il te faut 5 car juste pour la date. Tu peux coder en hexa le mois (1 - 12)... pour le reste...
 
 

Reply

Marsh Posté le 14-04-2004 à 13:24:25    

Eniac a écrit :

Salut,
 
J'ai une chaine datetime du type  
AAAAMMDDHHMMSS
20040314121025
 
et j'aimerais coder ça sur seulement 5 caractères alphanumérique


En binaire ça rentre, mais c'est binaire !


année    = 12 bits (0 -> 4095).
mois     =  4 bits (0 ->   15).
jour     =  5 bits (0 ->   31).
heures   =  5 bits (0 ->   31).
minutes  =  6 bits (0 ->   63).
secondes =  6 bits (0 ->   63).
         = 38 bits, soit 4.75 octets :o)


 
En alphanumérique c'est pas possible car simplement pour enregistrer l'heure (hh:mm:ss) il te faut 5 caractères en hexa (nombre de secondes ecoulees depuis 00h00m00s) ou 3 en base 64 (0..9,a..z,A..Z).
 
Il y a 31 536 000 secondes par année (année non bixestile).
Donc même en codant un nombre de secondes écoulées depuis une date fixe en base 64 tu ne pourrais avoir que 34 années environ. Par exemple si tu choisis le 01/01/2000 à 00h00m00s la date max serait (en gros) le 31/12/2034 à 23h59m59s. C'est pas génial.
 
ZZZZ (en base 64, voir plus haut) = 1 073 741 824.
 
Oups j'ai dit "base 64" mais en fait c'est 62 !


Message édité par darkoli le 14-04-2004 à 13:45:14
Reply

Marsh Posté le 14-04-2004 à 13:39:11    

Si il veut plus simple, il vire l'année, il lui reste donc 5 nombres à coder sur 5 caractères. Sachant que les nombres vont de 0 à 60 et que alphabet majuscule+minuscule+chiffres=26+26+10=62 possibilités, c'est pas si difficile à convertir.

Reply

Marsh Posté le 14-04-2004 à 13:55:08    

Cadeau:
 

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. //14 12 10 25
  4. char encode( int nb ){
  5.     // erreur
  6.     if( nb > 60 || nb < 0 ) return 0;
  7.    
  8.     // entre 0 et 25 => alphabet majuscule
  9.     if( nb < 26 ) return (char)('A'+nb);
  10.     // entre 25 et 52 => alphabet majuscule
  11.     if( nb < 52 ) return (char)('a'+nb-26);
  12.  
  13.     // entre 52 et 60compris => numerique
  14.     return (char)('0'+nb-52);
  15. }
  16. int decode( char c ){
  17.    
  18.     if( c >= 'A' && c <= 'Z' ) return (int)(c-'A');
  19.     if( c >= 'a' && c <= 'z' ) return (int)(c-'a'+26);
  20.     if( c >= '0' && c <= '9' ) return (int)(c-'0'+52);
  21.    
  22.     //erreur  
  23.     return -1;
  24. }
  25. void codeDateTime( char *date, char *code ){
  26.     //20040314121025
  27.     int i, pos=4;
  28.     for( i=0; i<5; i++ ){
  29.         int nb = (date[pos]-'0')*10 + (date[pos+1]-'0');
  30.         code[i] = encode( nb );
  31.         pos+=2;
  32.     }
  33. }
  34. void decodeDateTime( char* code, char* date ){
  35.     int i,pos=4;
  36.     strcpy( date, "xxxx" );
  37.    
  38.     for( i=0; i<5; i++ ){
  39.         sprintf( date+pos, "%02d", decode(code[i]) );
  40.         pos += 2;
  41.     }
  42. }
  43. int main(int argc, char *argv[])
  44. {
  45.   char code[6], dateDecod[20];
  46.   char *maDate = "20040314121025";
  47.  
  48.   codeDateTime( maDate, code );
  49.   code[5] = '\0';
  50.   printf( "Code de %s = %s\n", maDate, code );
  51.  
  52.   decodeDateTime( code, dateDecod );
  53.   dateDecod[14] = '\0';
  54.   printf( "Decode de %s = %s\n", code, dateDecod );
  55.  
  56.   system("PAUSE" );
  57.   return 0;
  58. }


 
 


Code de 20040314121025 = DOMKZ
Decode de DOMKZ = xxxx0314121025



Message édité par pascal_ le 14-04-2004 à 13:56:19
Reply

Marsh Posté le 14-04-2004 à 16:22:53    

Hello,  
 
merci pour vos réponses
le seul problème c'est que je ne suis pas case sensitive,
 
donc j'ai seulement 26 lettres + 10 chiffres comme possibiltés...
 
ça me prend la tête :)
 
et finalement je crois que je dois laisser les mois et l'année car je sinon je serai emmerdé tous les réveillons...


---------------
If you really want something, all the Universe conspires in helping you to achieve it.
Reply

Marsh Posté le 15-04-2004 à 12:09:13    

Eniac a écrit :

Hello,  
 
merci pour vos réponses
le seul problème c'est que je ne suis pas case sensitive,
 
donc j'ai seulement 26 lettres + 10 chiffres comme possibiltés...
 
ça me prend la tête :)
 
et finalement je crois que je dois laisser les mois et l'année car je sinon je serai emmerdé tous les réveillons...
 


Dans ce cas tu peux coder une date sur une période de deux ans max (si tu garde une précision à la seconde), par exemple tu peux enregistrer une date entre le 01/01/2000 à 00h00m00s et le 31/12/2001 à 23h59m59s c'est un peu limité en fait !
 
Quel est l'intervalle de date que tu dois gérer ?
De 1900 à 2100 ?
 
Sans les secondes tu peux gérer environ 114 ans.

Reply

Marsh Posté le 16-04-2004 à 12:07:41    

C'est pour Eniac (trop fatigué pour poster lui-même ;) ) : "à la limite, je veux bien virer les secondes s'il faut. L'intervalle de temps est de maintenant à dans 100 ans. Comment fais-tu pour coder 114 ans ?"

Reply

Marsh Posté le 16-04-2004 à 14:56:13    

36^5 = 60466176 (On a un nombre allant de 0 à 60466175).
Il y a 1440 minutes par jours.
Donc la valeur maximale représente une durée de 41990,399 jours.
Ce qui donne 114,96345 années (J'ai divisé par 365.25 mais c'est pas précis car 2100 ne sera pas bissextile par exemple).
 
Donc avec un nombre codé en base 36 avec un maximum de 5 positions on peut gérer presque 115 ans, reste à savoir si c'est suffisant.


Message édité par darkoli le 16-04-2004 à 14:56:56
Reply

Marsh Posté le 16-04-2004 à 16:28:17    

Pour compléter l'explication darkoli, tu dois définir une date comme étant un nombre de minutes supplémentaires par rapport à une date référence. Donc il faut :

  • - que tu définisses une date référence pour laquelle tu commences à compter. Par exemple, si tu prends le 01/01/2000 à 0 heure 0 minute tu pourras enregistrer des dates jusqu'en 2114 (environ)
  • - tu soustrais la date à cette date référence pour trouver le nombre de minutes de différence enter les deux dates . Essaye d'utiliser difftime() pour faire ça.
  • - tu transformes le nombre de minutes en base 36
  • - tu transformes chaque chiffre du nombre en base 36 en alphanumérique


Pour la lecture, il faut faire les opérations en sens inverse:

  • - alpha -> base36
  • - base36 -> base10
  • - ajouter ce nombre de minutes à la date de référence pour retrouver la bonne date. Peut-être qu'en ajoutant les minutes*60 directement à la date format time_t du c, ça fonctionne (à vérifier).


 
Sinon, par curiosité, pourquoi tu es obligé d'écrire une date comme ça ?


Message édité par pascal_ le 16-04-2004 à 16:29:20
Reply

Marsh Posté le 16-04-2004 à 16:28:17   

Reply

Marsh Posté le 19-04-2004 à 10:49:18    

ok merci, je crois que je devrais pouvoir m'en sortir
 
c'est quand même une fameuse prise de tête pour un si petit truc !
 
 
 
Une petite erreur je crois dans l'explication de Darkoli :
la valeur max ne serait-elle pas  
36^5 + 36^4 + 36^3 + ... 36^0 = 62 193 781 minutes = 118,2 ans
 
Vu que d'ici là je serai mort, je crois que si ça ne fonctionne plus, je ne serai pas là pour subir les représailles :) Oui c'est suffisant.
 
 
 
Une petite erreur aussi, je crois, dans l'explication de _pascal :
"- tu transformes chaque chiffre du nombre en base 36 en alphanumérique "
--> ça ne serait pas plutôt "tu transformes chaque nombre (0...35) en caractère alphanumérique ?
 
 
Pour ton info :

difftime()  
 
Finds the difference between two times.
 
double difftime( time_t timer1, time_t timer0 );
 
Return Value
 
difftime returns the elapsed time in seconds, from timer0 to timer1. The value returned is a double-precision floating-point number.
 
Parameters
 
timer1
Ending time
 
timer0
Beginning time

 
--> si j'ai le temps en secondes je suppose que je peux diviser la valeur de retour par 60 pour avoir le temps en minutes ? et ça tient bien compte des années bissextiles, etc, je suppose ?
 
 
Pour satisfaire ta curiosité, je suis sûr un projet qui consiste à utiliser un microcontrôleur intégrant serveur web pour faire de la récolte d'informations sur une ligne de production.  Je garde en RAM les informations que je récolte, et toutes les 5 minutes, je génère un fichier XML sur la flash du µC.  Un serveur interroge chaque µC, et via FTP, rappatrie ces fichiers.
 
C'est concernant la désignation de ces fichiers, qui est en dos-style (8 caract alphanum) que j'ai besoin de 3 lettres pour coder le nom de la machine hôte, et me démerder avec les 5 restants pour avoir qqch de significatif.  Un n° séquentiel n'est pas très explicite, et est source de problèmes, tandis que l'heure et la date ça me parait le plus intéressant.
 
Merci A+
 
 
 
 


---------------
If you really want something, all the Universe conspires in helping you to achieve it.
Reply

Marsh Posté le 19-04-2004 à 11:14:15    

Eniac a écrit :

Une petite erreur je crois dans l'explication de Darkoli :
la valeur max ne serait-elle pas  
36^5 + 36^4 + 36^3 + ... 36^0 = 62 193 781 minutes = 118,2 ans


Tu as 5 chiffres avec pour chacun 36 valeurs différentes possibles [0..9,a..z] donc tu as un total de 36*36*36*36*36 (36^5) possibilités sachant que tu peux utiliser la même valeur pour différents chiffres.
 
Tu peux aller de 0 à zzzzz en base 36 soit de 0 à 60466175 en base 10.
Pour t'en convaincre convertis à la main le nombre "zzzzz" (base 36) en base 10.
 
zzzzz [36] = (35 * 36^4) + (35 * 36^3) + (35 * 36^2) + (35 * 36) + 35 [10]


Message édité par darkoli le 19-04-2004 à 11:16:46
Reply

Marsh Posté le 19-04-2004 à 11:24:29    

autant pour moi !
 
j'ai tjs été nul dans ces trucs là ;)
 
sorry


---------------
If you really want something, all the Universe conspires in helping you to achieve it.
Reply

Marsh Posté le 29-04-2004 à 18:41:41    

Je continu dans le genre... (pour le fun seulement)
 
Seconde = 0...59 soit 5,9069 bits
Minutes = 0...59 soit 5,9069 bits
Heures = 0...23 soit 4,5850 bits
Jour = 0...31 soit 5 bits
Mois = 0...11 soit 3,5850 bits
Année = 0...9999 soit 13,2878 bits (forme 1)
 
Total 24,9838 bits sans l'année
et 38,2716 bits.
 
On dispose de 36 possibilités (A-Z et 0-9) soit 5,17 bits par caractères.
 
Roulement de tambours.... BROM BROM BROM... BROM BROM BROM...
 
TADA !!!
 
Il faut donc...
- 7,40 caractères soit 8 caractères avec l'année
- 4,83 caractères soit 5 caractères sans l'année
 
Sans l'année, tu as ta solution, à toi de la mettre en pratique !


Message édité par christophe_d13 le 29-04-2004 à 18:42:34
Reply

Marsh Posté le 30-04-2004 à 08:28:01    

Salut,
 
Solution finale adoptée : 6 caractères, on garde uniquement le chiffre de l'année (par exemple 4 pour 2004) ce qui fait une période de 10 ans, juste ce qu'il faut.
 
En prenant les valeurs max pour chaque champ, il faut 30 bits, soit 6*5 bits et on peut coder chaque groupe de 5 bits par un caractère 0...9 A...Z.  
 
Je ne prend pas de date de "référence", c'est tout aussi simple comme ça.
 
Merci A+


---------------
If you really want something, all the Universe conspires in helping you to achieve it.
Reply

Marsh Posté le 01-05-2004 à 00:05:49    

Alors il y a un problème !
 
Les minutes et les secondes sont sur combien de bits ?

Reply

Marsh Posté le 01-05-2004 à 00:34:21    

2**6 > 60{minutes, secondes} -> 6 bits sont nécessaires

Reply

Marsh Posté le 01-05-2004 à 02:16:40    

C'est bien ce que je dis, il y a un problème !
Sauf s'il supprime un bit pour minutes et secondes et conserve une présion de 2 secondes et 2 minutes...
Mais je vois pas l'intérêt.
 
Donc j'en remet une couche l'heure tient sur 16,4 bits.
Avec 6 caractères (soit 31 bits environ), il reste 14,6 bits. En ajoutant le mois et le jour, il reste environ 6 bits.
 
Mais bon, que de prise de tête... Le plus simple est de faire un timestamp commençant par exemple à 0:00:00 1/1/1980... Cela laisse une marche de pas mal d'années... (Même si ce n'est pas une solution viable pour l'avenir)


Message édité par christophe_d13 le 01-05-2004 à 02:23:10
Reply

Marsh Posté le 04-05-2004 à 08:48:32    

Vous trouverez ma démarche expliquée en clair ici
 
http://users.skynet.be/fa353969/NameLogic.pdf
 
 
 
La fonction C qui s'en charge :
 
Arguments :

Code :
  1. char XMLPath[]= par exemple c:\XML
  2. char machinename[] = par exmple LP
  3. TimeDate_Structure td = contient la date et l'heure (qui l'eut cru !)


 

Code :
  1. FILE *CreateFileName(char machinename[], TimeDate_Structure td, char XMLPath[])
  2. {
  3.    FILE *pstream ;
  4. char filename[64] ; //c:\(3)+mach name(2)+datetime(6)+extension(4)+endline caracter(1)
  5. unsigned long converted_td;    //numberic value of datetime string
  6.    int i;
  7.    int filelen;
  8.    //insert the path where XML files will be generated
  9.    strcpy(filename,XMLPath);
  10.    //insert two letters for machine name ;
  11.    strcat(filename,machinename);
  12.    //convert the datetime string to a numeric value
  13.    //REM : year%10 because the only fourth digit is used (three first are ignored)
  14.    converted_td=(((((((((((td.yr%10)<<4)|td.mn)<<5)|td.dy)<<5)|td.hr)<<6)|td.min)<<6)|td.sec) ;
  15.    //save the lenght of the actual file name
  16.    filelen=strlen(filename);
  17.    //take the five lastest bits of "converted_td" and convert them to 0,1...9,A,B...Z
  18. for(i=(filelen+5);i>=filelen;i--)
  19. {
  20.     if((converted_td%32)>=0 && (converted_td%32)<=9) //0...9
  21.   filename[i]=(char)((converted_td%32)+48) ; //48 means "0" in ASCII code
  22.       else if((converted_td%32)>=10 && (converted_td%32)<=35)    //A...Z
  23.   filename[i]=(char)((converted_td%32)+65-10) ; //65 means "A" in ASCII code
  24.       else
  25.       printf("Warning ! The 5 bits to convert are not in the correct range\n" );
  26.  converted_td = converted_td >> 5 ; //right shift to reach next five bits
  27. }
  28.    //put the endline caracter (erased by last loop)
  29.    filename[filelen+6]='\0' ;
  30.    //insert the file extension
  31.    strcat(filename,".xml" );
  32.    //create the file
  33. pstream=fopen(filename,"wt" );
  34.    if(pstream==NULL)
  35.     printf("Error - Impossible to create file %s\n",filename);
  36. return pstream;
  37. }


---------------
If you really want something, all the Universe conspires in helping you to achieve it.
Reply

Marsh Posté le 05-05-2004 à 11:50:33    

//48 means "0" in ASCII code  
 
 
bien essayé tu aurais du écrire
 
//48 means '0' in ASCII code  
 
 
ou alors '0' mais se faut trop simple ///
 
 
 
(converted_td%32)<=35
 
mince alors ...

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed