Fonction opposée a FormatDateTime

Résolu
Sat83
Messages postés
166
Date d'inscription
mardi 11 novembre 2003
Statut
Membre
Dernière intervention
13 octobre 2008
- 11 janv. 2008 à 11:01
Caribensila
Messages postés
2527
Date d'inscription
jeudi 15 janvier 2004
Statut
Membre
Dernière intervention
16 octobre 2019
- 13 janv. 2008 à 23:40
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

Cirec
Messages postés
3832
Date d'inscription
vendredi 23 juillet 2004
Statut
Modérateur
Dernière intervention
17 février 2022
48
12 janv. 2008 à 18:33
Voilà j'ai trouvé pourquoi

C'est l'utilisation du ComboBox.Text qui "évite" le plantage

je conseille donc de laisser le fameux " + #0" il vous évitera de chercher pendant des heures le pourquoi du comment du plantage

 
@+
Cirec

<hr siz="" />
0
japee
Messages postés
1727
Date d'inscription
vendredi 27 décembre 2002
Statut
Modérateur
Dernière intervention
6 novembre 2021
8
12 janv. 2008 à 19:00
Bien vu, Cirec. C'est sans appel.

A noter que tous les Captions et Text de la VCL (Edit, Memo (Memo.Text et Memo.Lines[x]), Label, Button, etc...) que j'ai testés produisent le même effet. Ils rajoutent donc automatiquement un caractère (#0, ou bien #13#10 ?) à la fin...
Ça me laisse perplexe.
0
japee
Messages postés
1727
Date d'inscription
vendredi 27 décembre 2002
Statut
Modérateur
Dernière intervention
6 novembre 2021
8
12 janv. 2008 à 19:06
Je retire "ils ajoutent automatiquement #13#10" : ça n'a pas de sens.
Donc, ils ajoutent un zéro terminal.
0
Cirec
Messages postés
3832
Date d'inscription
vendredi 23 juillet 2004
Statut
Modérateur
Dernière intervention
17 février 2022
48
12 janv. 2008 à 19:15
Ca va même plus loin que ça :

Var aStr1 : String = '19921905'+#0;

procedure TForm1.Button4Click(Sender: TObject);

begin
  Label1.Caption := ReverseDateT(aStr1); // Plante

end;

procedure TForm1.Button5Click(Sender: TObject);
begin
  aStr1 : =  aStr1 ;
  Label1.Caption := ReverseDateT(aStr1); // Ne plante pas
end;

Var aStr2 : String = '19921905';

procedure TForm1.Button6Click(Sender: TObject);

begin

  aStr2 :=   aStr2 ;

  Label1.Caption := ReverseDateT(aStr2); // Ne plante pas

end;

si quelqu'un a une explication ... je suis preneur

 
@+
Cirec

<hr siz ="" />
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
WhiteHippo
Messages postés
1154
Date d'inscription
samedi 14 août 2004
Statut
Membre
Dernière intervention
5 avril 2012
2
12 janv. 2008 à 20:30
Bonsoir

Il faut se mefier avec la manipulation des PChar. Si on reprend ta fonction :

  Pr := PChar(Str);         
  // Delphi fait une copie de la chaine Str                          
  // puis met l'adresse de celle ci dans dans Pr
  //
  // Pr                          
  // |                          
  // V                          
  // '12345678'#0                           
  //                           
                            
  Inc(Pr, Length(Str) - 2); 
  //
  //        Pr                          
  //        |                          
  //        V                          
  // '12345678'#0                           
  //                           
 
  D := Pr;                  
  // Comme D a été déclaré en tant que string Delphi fait
  // une copie du PChar dans la chaine D soit '78'#0
  //
  //        Pr                          
  //        |                          
  //        V                          
  // '12345678'#0                           
  //                             
 
  Pr^ := #0;
  // Là on réduit sauvagement la taille du PChar originel
  //         Pr                          
  //         |                          
  //         V                          
  // '123456'#0'8'#0                           
  //                             
  // Et on s'apperçoit que le bout '8'#0 est en quelque sorte perdu
  // Ce qui je suppose pose dans certaines conditions des problèmes
  // de désallocations et/ou des exceptions.

Il faut être très très prudent avec la manipulation directe des PChar. Les programmeurs en C connaissent d'ailleurs très bien les nombreux problèmes que ceux ci posent.

N.B. Pour info j'aurais plutôt ecris la fonction ainsi :

type
  TDatePtr = ^TDate ;
  TDate =  packed record
    Y : array[0..3] of char ;
    M,D : array[0..1] of char ;
  end ;



Function ReverseDateT(Const Str : String): String;
Var
  P : PChar;
  Date : TDatePtr absolute P ;
Begin
  P := PChar(Str);
  Result := Format('%.2s/%.2s/%.4s', [Date.D, Date.M, Date.Y]);
End;


Cordialement. <hr />"L'imagination est plus importante que le savoir." Albert Einstein
0
japee
Messages postés
1727
Date d'inscription
vendredi 27 décembre 2002
Statut
Modérateur
Dernière intervention
6 novembre 2021
8
12 janv. 2008 à 20:51
Je pense avoir compris.

La VCL passe la main à l'API et le string est transformé en chaîne C à zéro terminal.

Il suffit de faire ce test :

procedure TForm1.Button1Click(Sender: TObject);
begin
  Button1.Caption := '1992' + #0 + '0518';
  ShowMessage(Button1.Caption);
  // encore plus fort! :
  Label1.Caption := Button1.Caption;
end;

La chaîne obtenue sera "1992", le caractère #0 marquant la fin de chaîne en C.
Étonnant, non ?

A +
0
Cirec
Messages postés
3832
Date d'inscription
vendredi 23 juillet 2004
Statut
Modérateur
Dernière intervention
17 février 2022
48
12 janv. 2008 à 21:14
@WhiteHippo :

Merci pour ces explications mais je savais ce que cela allait "provoquer"
d'ailleurs c'est l'effet souhaité dans ce cas bien précis.

Mais ceci n'explique pas le problème évoqué plus haut !!!!

Par contre ton approche me plait bien je dois avouer que je n'y avais pas pensé pourtant j'utilise souvent "l'astuce" du ABSOLUTE

@Japee :

J'ai pas bien compris le "encore plus fort" ou c'est nouveau mon PC qui est hanté

je trouve ceci plus "spectaculaire":

procedure TForm1.Button1Click(Sender: TObject);
Var s : String;
begin
  S := '1992' + #0 + '0518';
  Button1.Caption := S;
  ShowMessage(Button1.Caption);
  // encore plus fort! :
  Label1.Caption := IntToStr(Length(s));
end;

 
@+
Cirec

<hr siz="" />
0
japee
Messages postés
1727
Date d'inscription
vendredi 27 décembre 2002
Statut
Modérateur
Dernière intervention
6 novembre 2021
8
12 janv. 2008 à 21:16
Ouais, avant de manipuler les PChar à la légère, on va y réfléchir à 2 fois...

Encore plus probant que mon test précédent :

procedure TForm1.Button1Click(Sender: TObject);
var
  A, B: string;
  LA, LB, LC: Integer;
begin
  A := '1992' + #0 + '0518';
  LA := Length(A);
  ShowMessage(IntToStr(LA));
  B := A;
  LB := Length(B);
  ShowMessage(IntToStr(LB));
  Label1.Caption := B;
  LC := Length(Label1.Caption);
  ShowMessage(IntToStr(LC));
  // on obtient respectivement : 9, 9, 4
end;

Je crois que là c'est clair.
0
japee
Messages postés
1727
Date d'inscription
vendredi 27 décembre 2002
Statut
Modérateur
Dernière intervention
6 novembre 2021
8
12 janv. 2008 à 21:21
@Cirec :

Par "encore plus fort", je voulais dire qu'en appelant ShowMessage, tu t'attends à passer par l'API, donc à ce que ta chaîne soit convertie en C, donc tronquée à l'endroit du "#0".
Alors qu'en l'attribuant à un "caption" ou autre "text", on ne manque pas d'être surpris...
0
Cirec
Messages postés
3832
Date d'inscription
vendredi 23 juillet 2004
Statut
Modérateur
Dernière intervention
17 février 2022
48
12 janv. 2008 à 21:28
il n'y a rien d'extraordinaire dans cela ...

cela prouve juste que les Caption, Text et autres soit disant String sont en fait des PChar

Par contre ce qui est étonnant c'est que (sur le problème cité plus haut) le simple fait de réaffecter la variable String avec sa propre valeur empêche ce fameux bug

Et comme ça c'est encore plus bizarre !!!!

Var aStr1 : String = '19921905';
procedure TForm1.Button5Click(Sender: TObject);
begin
  ShowMessage(IntToStr(Length(aStr1)));
  aStr1 :=  aStr1 ;
  Label1.Caption := ReverseDateT(aStr1);
  ShowMessage(IntToStr(Length(aStr1)));
end;

on ne peut donc pas dire que Delphi rajoute un zéro terminal dans ce cas précis

 
@+
Cirec

<hr siz="" />
0
Cirec
Messages postés
3832
Date d'inscription
vendredi 23 juillet 2004
Statut
Modérateur
Dernière intervention
17 février 2022
48
12 janv. 2008 à 21:32
Mais elle est troqué chez moi, dans les deux cas j'obtiens  1992
avec ce code :
procedure TForm1.Button1Click(Sender: TObject);
begin
  Button1.Caption := '1992' + #0 + '0518';
  ShowMessage(Button1.Caption);
  // encore plus fort! :
  Label1.Caption := Button1.Caption;
end;

 
@+
Cirec

<hr siz="" />
0
japee
Messages postés
1727
Date d'inscription
vendredi 27 décembre 2002
Statut
Modérateur
Dernière intervention
6 novembre 2021
8
12 janv. 2008 à 21:55
Et ça, c'est pas mal non plus :

var aStr1: string;  // <- OK
procedure TForm1.Button3Click(Sender: TObject);
//var aStr1: string;  // <- violation d'accès
begin
  aStr1 := '19920519';
  //Label1.Caption := ReverseDateT(aStr1); // <- OK
  Label1.Caption := ReverseDateT('19920519'); // <- violation d'accès
end;

aaarrrgggghhh...
0
Cirec
Messages postés
3832
Date d'inscription
vendredi 23 juillet 2004
Statut
Modérateur
Dernière intervention
17 février 2022
48
12 janv. 2008 à 22:08
Oui et ceci plante :
Var aStr1 : String = '19921905';
procedure TForm1.Button1Click(Sender: TObject);
begin
  Label1.Caption := ReverseDateT(aStr1);
end;

C'est vraiment déconcertant ... non

 
@+
Cirec

<hr siz="" />
0
Caribensila
Messages postés
2527
Date d'inscription
jeudi 15 janvier 2004
Statut
Membre
Dernière intervention
16 octobre 2019
18
13 janv. 2008 à 17:24
ET ALORS ..?







Y'a 1 065 121 mecs qui attendent vos conclusions !
0
japee
Messages postés
1727
Date d'inscription
vendredi 27 décembre 2002
Statut
Modérateur
Dernière intervention
6 novembre 2021
8
13 janv. 2008 à 21:19
1 065 121 mecs, ah quand même ?
Et quasiment pas une fille...
Faut dire qu'on a une tellement grande gueule (surtout certains, suivez mon regard), que je comprends qu'elles se fassent discrètes.

Ma conclusion, elle tient en quelques mots.
Delphi nous fournit un type de chaîne facile à manier, souple, performant, que le monde entier (et surtout les autres langages de programmation) nous envie : AnsiString.
A moins d'y être obligés, ou d'être un peu maso, je ne vois pas ce qui nous pousserait à utiliser PChar. Sauf à vouloir fréquenter l'api windows, ou autre dll codée en C...

Mais maso, on l'est tous un peu sur delphifr, sinon on passerait pas notre temps à se torturer les neurones. On se servirait de la VCL sans chercher à comprendre et puis c'est tout !
0
Caribensila
Messages postés
2527
Date d'inscription
jeudi 15 janvier 2004
Statut
Membre
Dernière intervention
16 octobre 2019
18
13 janv. 2008 à 23:40
C'était un "mecs" générique, bien sûr...  :)))


Il est quand même difficile de ne pas se frotter de temps en temps à l'API Windows ou
aux DLL. Mieux vaut comprendre PChar, tout comme les pointeurs d'ailleurs.
Il faut reconnaître que Delphi nous fait la vie belle avec tout ça. Peut-être un peu trop question "ouverture d'esprit".
La description complète du format interne de ces chaînes n'est pas documentée par Borland, qui se reserve le droit de modifier ce format interne dans les versions à venir.
Comme le suggérait Whitehippo, gare au débordement d'intervalle et à la corruption mémoire avec PChar!
Et le jour où on commence à utiliser WideString avec l'Unicode, on se sent un peu handicapé.

M'enfin, Delphi c'est quand même super...  et vous êtes là!!! 
0