Fonction opposée a FormatDateTime [Résolu]

Signaler
Messages postés
166
Date d'inscription
mardi 11 novembre 2003
Statut
Membre
Dernière intervention
13 octobre 2008
-
 Caribensila -
Bonjour,

Je suis a la recherche d'une fonction qui fait l'inverse de la fonction FormatDateTime.

Je m'explique: plutot que d'avoir en entrée un TDateTime et un formatage, et recuperer en sortie une String, je souhaiterais une fonction du style:

functionFormatStrToDateTime(const Format: string; Date: string): TDateTime;

où on passe une string contenant une date formatée d'une manière "speciale", et où on passe une string contenant le format a utilisé pour decoder cette date.

J'en ai besoin parce que je recoit un fichier ou les date sont formatée en YYYYMMDD (par exemple '19920519' pour le 19 mai 1992), et donc la fonction StrToDate ne fonctionne pas.

Etant donnée que le format de date peut changé, j'aimerais donc savoir si il existe une fonction telle que celle decrite çi-dessus.

Je sais pas si mes explications sont claires, mais si jamais vous avez une idée, je suis preneur!

Merci d'avance

36 réponses

Messages postés
1721
Date d'inscription
vendredi 27 décembre 2002
Statut
Modérateur
Dernière intervention
30 août 2020
4
Salut,

Oui, j'aurais fait comme Loda.
Juste un point de détail :

result:=EncodeDate(StrToInt(copy(str,1,4)),StrToInt(copy(str,5,2)),StrToInt(copy(str,7,2)));

Il s'agit visiblement d'une erreur d'inattention
Messages postés
1023
Date d'inscription
dimanche 1 août 2004
Statut
Membre
Dernière intervention
17 août 2008
1
Salut !
La rapidité n'est pas fonction du nombre de lignes !!
D'ailleurs, la fonction la plus rapide que j'ai pu trouver est :

<hr size="2" width="100%" />function MyStrToDateTime(const S: string): TDateTime;
const
  CDigits: array['0'..'9'] of Integer = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
var
  Y, M, D: Integer;
begin
  Y := CDigits[S[1]] * 1000
     + CDigits[S[2]] * 100
     + CDigits[S[3]] * 10
     + CDigits[S[4]];
  M := CDigits[S[5]] * 10
     + CDigits[S[6]];
  D := CDigits[S[7]] * 10
     + CDigits[S[8]];
  Result := EncodeDate(Y, M, D);
end;
<hr size="2" width="100%" />
NB: il y a bien une gestion d'erreurs car la fonction déclenche un EBoundError si un des caractère n'est pas un chiffre ou si la chaîne est trop courte.
NB2: elle est 11 fois plus rapide que la version modifiée de Loda par japee et pourant... 11 fois plus longue (en lignes de code) !

A+
Flo

Ressources Delphi, sources, tutoriaux, actu, ...: www.mx-dev.nethttp://te%3C/body
Messages postés
991
Date d'inscription
samedi 25 octobre 2003
Statut
Membre
Dernière intervention
29 août 2013
5
bah ........ StrToDate !!!
Messages postés
166
Date d'inscription
mardi 11 novembre 2003
Statut
Membre
Dernière intervention
13 octobre 2008

Ben comme expliqué dans mon premier poste, StrToDate ne fonctionne pas, puisque le format date n'est pas reconnu.

J'ai une exception EConvertError  ''19920519' n'est pas une date correcte'
Messages postés
166
Date d'inscription
mardi 11 novembre 2003
Statut
Membre
Dernière intervention
13 octobre 2008

En attendant de pouvoir trouver mieux je me suis fait une petite fonction:

function StrToDatePerso(date : string) : TDate;
var
     y, m, d : integer;
begin
   y  :=  StrToInt(date[1])*1000
        + StrToInt(date[2])*100
        + StrToInt(date[3])*10
        + StrToInt(date[4]);

   m  :=  StrToInt(date[5])*10
        + StrToInt(date[6]);

   d  :=  StrToInt(date[7])*10
        + StrToInt(date[8]);

   StrToDatePerso := EncodeDate( y, m, d );
end;

C'est une solution provisoire pour que je puisse continué à avancer dans mon projet, donc je suis toujours à l'ecoute d'eventuelle solution que vous auriez a proposer...

Merci d'avance....
Messages postés
814
Date d'inscription
vendredi 3 novembre 2000
Statut
Membre
Dernière intervention
30 juillet 2009
3
salut,

c'est peut-être pas le plus "optimizé", mais ça marche:

function yyyymmddStrToDateTime(Str:String):TDateTime;
begin
 //ajout des tests si tu veux (length, ...)
  result:=EncodeDate(StrToInt(copy(str,0,4)),StrToInt(copy(str,5,2)),StrToInt(copy(str,7,2)));
end;

bon code,

Loda
<hr size="2" width="100%" />Se poser les bonnes questions est le premier pas pour trouver les bonnes réponses.
Messages postés
166
Date d'inscription
mardi 11 novembre 2003
Statut
Membre
Dernière intervention
13 octobre 2008

Merci pour ces reponses...

Je testerais vos propositions  lundi!

Mais bon, le problème reste que ces fonctions sont spécifiques au format YYYYMMDD... (vous me direz c'est mieux que rien, et je suis d'accord!).

Dommage qu'il n'existe pas de solution 'miracle' existante permettant d'obtenir un TDate a partir de 2 string (une avec la date, l'autre avec le formatage).

Merci a vous en tout cas...
Messages postés
1721
Date d'inscription
vendredi 27 décembre 2002
Statut
Modérateur
Dernière intervention
30 août 2020
4
Belle démonstration de ton talent, Flo !
Messages postés
4202
Date d'inscription
samedi 16 octobre 2004
Statut
Modérateur
Dernière intervention
13 juin 2020
32
function StrYMDToDate(const S : string {yyyymmdd}): TDateTime;
begin
  if Length(S) <> 8 then
    exit;

  result := EncodeDate(
              word(StrToIntDef( Copy(S, 1, 4), 1900)),
              word(StrToIntDef( Copy(S, 5, 2), 1)),
              word(StrToIntDef( Copy(S, 7, 2), 1))
            );
end;






<hr size="2" width="100%" />


http://deefaze.gnomz.com
Messages postés
1154
Date d'inscription
samedi 14 août 2004
Statut
Membre
Dernière intervention
5 avril 2012
2
Bonjour

Va voir ici tu y trouveras peut être ce que tu souhaites.

Cordialement.
<hr />"L'imagination est plus importante que le savoir." Albert Einstein
Messages postés
3818
Date d'inscription
vendredi 23 juillet 2004
Statut
Modérateur
Dernière intervention
18 septembre 2020
34
Salut,

voici une approche différente avec un résultat différent
elle pourra peut être servir ne serait-ce que sur un plan éducatif

En entré nous avons : '19920519' {String}
Et en sortie nous obtenons '19/05/1992' {String} utilisable avec StrToDate

Function ReverseDate(Const Str : String): String;

Var P, Pr : PChar;
    L : Integer;

    Y, M, D : String;
Begin
  P := PChar(Str + #0);
  L := Length(Str);
  Pr := P;
  Inc(Pr,
L-2); // on se place à la fin
de la chaine moins 2 caractères
  D := Pr;
  Pr^ := #0; // on déplace la fin de la
chaine et on recommence
  Dec(Pr, 2);

  M := Pr;
  Pr^ := #0;
  Dec(Pr, 4);
  Y := Pr;
  Result := Format('%s/%s/%s', [D, M, Y]);
End ;
<center>Highlighted with Pas2HTML </center>
@+
Cirec

<hr siz ="" />
Messages postés
1721
Date d'inscription
vendredi 27 décembre 2002
Statut
Modérateur
Dernière intervention
30 août 2020
4
Hello,

Oh oui, Cirec, très très intéressant pour qui veut comprendre le fonctionnement des pointeurs sur les chaînes à 0 terminal.

Mais ne penses-tu pas qu'un seul PChar suffirait ?

Function ReverseDate(Const Str : String): String;
Var Pr : PChar;
    L : Integer;
    Y, M, D : String;
Begin
  L := Length(Str);
  Pr := PChar(Str + #0);
  Inc(Pr, L-2); // on se place à la fin de la chaine moins 2 caractères
  D := Pr;
  Pr^ := #0; // on déplace la fin de la chaine et on recommence
  Dec(Pr, 2);
  M := Pr;
  Pr^ := #0;
  Dec(Pr, 4);
  Y := Pr;
  Result := Format('%s/%s/%s', [D, M, Y]);
End;

A +
Messages postés
3818
Date d'inscription
vendredi 23 juillet 2004
Statut
Modérateur
Dernière intervention
18 septembre 2020
34
Oui tu as entièrement raison

En fait le deuxième pointeur est un vestige de la première mouture,
j'avais l'intention d'utiliser un pointeur pour l'entrée (Str) et l'autre pour la sortie (Result) ... puis j'ai changer d'avis en oubliant d'éliminer  le pointeur en trop ...

 
@+
Cirec

<hr siz="" />
Messages postés
3818
Date d'inscription
vendredi 23 juillet 2004
Statut
Modérateur
Dernière intervention
18 septembre 2020
34
Petite précision ... ce n'est une chaine à zéro terminal mais
une chaine à double zéro terminal
c'est justement cette différence qui permet de déplacer la fin de la chaine ...

Pour s'en rendre compte il suffit de remplacer :
  Pr := PChar(Str + #0);
Par
  Pr := PChar(Str);
Pour obtenir une belle exception à la première instruction du type :
  Pr^ := #0;

 
@+
Cirec

<hr siz="" />
Messages postés
1721
Date d'inscription
vendredi 27 décembre 2002
Statut
Modérateur
Dernière intervention
30 août 2020
4
Sous D4 et D7, ça passe :
Pr := PChar(Str);
ne provoque aucune exception à l'exécution...

Encore une différence entre D 2007 et les versions précédentes ?

Bizarre...
Messages postés
3818
Date d'inscription
vendredi 23 juillet 2004
Statut
Modérateur
Dernière intervention
18 septembre 2020
34
L'exception se déclanche par sur cette instruction mais sur :
Pr^ := #0;

Testé sous D7 !!!!

 
@+
Cirec

<hr siz="" />
Messages postés
1721
Date d'inscription
vendredi 27 décembre 2002
Statut
Modérateur
Dernière intervention
30 août 2020
4
Testé sous D7 aussi :

Voici ta fonction modifiée :

function ReverseDateT(const Str: string): string;
var
  Pr : PChar;
  Y, M, D : string;
begin
  Pr := PChar(Str); // <- modif ici
  Inc(Pr, Length(Str) - 2);
  D := Pr;
  Pr^ := #0; // <- pas d'exception
  Dec(Pr, 2);
  M := Pr;
  Pr^ := #0; // <- pas d'exception
  Dec(Pr, 4);
  Y := Pr;
  Result := Format('%s/%s/%s', [D, M, Y]);
end;

Et ça passe...
Messages postés
3818
Date d'inscription
vendredi 23 juillet 2004
Statut
Modérateur
Dernière intervention
18 septembre 2020
34
Arf ... moi j'ai une exception à la première instruction :
Pr^:= #0;

Sous D7 et TurboDelphi  !!!!

peut être une directive de compilation ????

 
@+
Cirec

<hr siz="" />
Messages postés
3818
Date d'inscription
vendredi 23 juillet 2004
Statut
Modérateur
Dernière intervention
18 septembre 2020
34
Je viens de tester le code sur une autre machine (PIII) et sur un AMD

et j'ai toujours le même problème ... si je retire "+ #0" le code plante
et avec 3 versions de Delphi différentes ????

Quelqu'un pourrait-il tester cette procédure (avec et sans "+ #0") et nous dire ce qu'il en est
S.V.P .... Merci

 
@+
Cirec

<hr siz="" />
Messages postés
1721
Date d'inscription
vendredi 27 décembre 2002
Statut
Modérateur
Dernière intervention
30 août 2020
4
Ouais, si quelqu'un pouvait être sympa et tester ça...

C'est facile, il faut juste :

- 1 TEdit,
- 1 TLabel,
- 1 TButton.

Le code :

function ReverseDateT(const Str: string): string;
var
  Pr : PChar;
  Y, M, D : string;
begin
  Pr := PChar(Str);
  Inc(Pr, Length(Str) - 2);
  D := Pr;
  Pr^ := #0;
  Dec(Pr, 2);
  M := Pr;
  Pr^ := #0;
  Dec(Pr, 4);
  Y := Pr;
  Result := Format('%s/%s/%s', [D, M, Y]);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  ADateTime: TDateTime;
begin
  ADateTime := StrToDate(ReverseDateT(ComboBox1.Text));
  Label1.Caption := DateTimeToStr(ADateTime);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Edit1.Text := '19920519';
end;

Voilà. Sinon j'en connais au moins 1 qui va avoir du mal à s'endormir ce soir...

P-S: Cirec, tu as reçu mon zip ? Des fois que...