Fonction opposée a FormatDateTime [Résolu]

Sat83 172 Messages postés mardi 11 novembre 2003Date d'inscription 13 octobre 2008 Dernière intervention - 11 janv. 2008 à 11:01 - Dernière réponse :  Caribensila
- 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
Afficher la suite 

Votre réponse

36 réponses

Meilleure réponse
japee 1799 Messages postés vendredi 27 décembre 2002Date d'inscription 19 juillet 2018 Dernière intervention - 11 janv. 2008 à 18:00
3
Merci
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

Merci japee 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 94 internautes ce mois-ci

Commenter la réponse de japee
Meilleure réponse
florenth 1105 Messages postés dimanche 1 août 2004Date d'inscription 17 août 2008 Dernière intervention - 11 janv. 2008 à 19:00
3
Merci
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

Merci florenth 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 94 internautes ce mois-ci

Commenter la réponse de florenth
Guillemouze 1015 Messages postés samedi 25 octobre 2003Date d'inscription 29 août 2013 Dernière intervention - 11 janv. 2008 à 13:31
0
Merci
bah ........ StrToDate !!!
Commenter la réponse de Guillemouze
Sat83 172 Messages postés mardi 11 novembre 2003Date d'inscription 13 octobre 2008 Dernière intervention - 11 janv. 2008 à 13:43
0
Merci
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'
Commenter la réponse de Sat83
Sat83 172 Messages postés mardi 11 novembre 2003Date d'inscription 13 octobre 2008 Dernière intervention - 11 janv. 2008 à 13:53
0
Merci
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....
Commenter la réponse de Sat83
cs_Loda 900 Messages postés vendredi 3 novembre 2000Date d'inscription 30 juillet 2009 Dernière intervention - 11 janv. 2008 à 17:11
0
Merci
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.
Commenter la réponse de cs_Loda
Sat83 172 Messages postés mardi 11 novembre 2003Date d'inscription 13 octobre 2008 Dernière intervention - 11 janv. 2008 à 19:50
0
Merci
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...
Commenter la réponse de Sat83
japee 1799 Messages postés vendredi 27 décembre 2002Date d'inscription 19 juillet 2018 Dernière intervention - 11 janv. 2008 à 20:32
0
Merci
Belle démonstration de ton talent, Flo !
Commenter la réponse de japee
f0xi 4304 Messages postés samedi 16 octobre 2004Date d'inscription 9 mars 2018 Dernière intervention - 11 janv. 2008 à 20:56
0
Merci
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
Commenter la réponse de f0xi
WhiteHippo 1270 Messages postés samedi 14 août 2004Date d'inscription 5 avril 2012 Dernière intervention - 12 janv. 2008 à 12:01
0
Merci
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
Commenter la réponse de WhiteHippo
Cirec 4231 Messages postés vendredi 23 juillet 2004Date d'inscription 3 août 2018 Dernière intervention - 12 janv. 2008 à 13:11
0
Merci
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 ="" />
Commenter la réponse de Cirec
japee 1799 Messages postés vendredi 27 décembre 2002Date d'inscription 19 juillet 2018 Dernière intervention - 12 janv. 2008 à 14:19
0
Merci
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 +
Commenter la réponse de japee
Cirec 4231 Messages postés vendredi 23 juillet 2004Date d'inscription 3 août 2018 Dernière intervention - 12 janv. 2008 à 14:44
0
Merci
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="" />
Commenter la réponse de Cirec
Cirec 4231 Messages postés vendredi 23 juillet 2004Date d'inscription 3 août 2018 Dernière intervention - 12 janv. 2008 à 15:04
0
Merci
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="" />
Commenter la réponse de Cirec
japee 1799 Messages postés vendredi 27 décembre 2002Date d'inscription 19 juillet 2018 Dernière intervention - 12 janv. 2008 à 16:10
0
Merci
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...
Commenter la réponse de japee
Cirec 4231 Messages postés vendredi 23 juillet 2004Date d'inscription 3 août 2018 Dernière intervention - 12 janv. 2008 à 16:14
0
Merci
L'exception se déclanche par sur cette instruction mais sur :
Pr^ := #0;

Testé sous D7 !!!!

 
@+
Cirec

<hr siz="" />
Commenter la réponse de Cirec
japee 1799 Messages postés vendredi 27 décembre 2002Date d'inscription 19 juillet 2018 Dernière intervention - 12 janv. 2008 à 16:20
0
Merci
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...
Commenter la réponse de japee
Cirec 4231 Messages postés vendredi 23 juillet 2004Date d'inscription 3 août 2018 Dernière intervention - 12 janv. 2008 à 16:24
0
Merci
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="" />
Commenter la réponse de Cirec
Cirec 4231 Messages postés vendredi 23 juillet 2004Date d'inscription 3 août 2018 Dernière intervention - 12 janv. 2008 à 17:27
0
Merci
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="" />
Commenter la réponse de Cirec
japee 1799 Messages postés vendredi 27 décembre 2002Date d'inscription 19 juillet 2018 Dernière intervention - 12 janv. 2008 à 17:43
0
Merci
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...
Commenter la réponse de japee

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.