DecodeDateTime et TDateTime

EricStib Messages postés 13 Date d'inscription vendredi 23 février 2007 Statut Membre Dernière intervention 26 avril 2007 - 25 avril 2007 à 11:13
cs_Loda Messages postés 814 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 30 juillet 2009 - 26 avril 2007 à 13:14
Bonjour à tous,

Le but: Entrer un (grand) nombre et en retrouver l'équivalent en nombre d'années, de mois, de jours, d'heures, de minutes et de secondes.

J'ai utilisé la méthode classique avec les div et mod... cela fonctionne bien dans la gamme du type Integer.

Si on veux utiliser des nombres plus grand, il faut passer par le type Double... mais les div et mod ne sont plus applicables.

Donc, j'en viens à l'utilisation de la fonction DecodeDateTime qui semble apporter une solution:







procedure TForm1.AvecTdateTime;



var



  dateInput : TDateTime;



  Year, Month, Day, Hour, Minute, Second, MilliSecond : word;



begin



    dateInput := StrToDateTime(L_EdNbresSecondes.text);



    DecodeDateTime(dateInput,year,month,day,hour,minute,second,millisecond);



    with RichEdit1.Lines do



            begin



                Add('Nombres d''années :' + IntToStr(year));



                Add('Nombre de mois :' + IntToStr(month));



                Add('Nombre de jours :' + IntToStr(day));



                Add('Nombre d''heures :' + IntToStr(hour));



                Add('Nombre de minutes : ' +
IntToStr(minute));



                Add('Nombre de secondes :' + IntToStr(second));



                //Add(IntToStr (High (Integer)));



            end;



end;




Mais ici, j'obtiens un message d'erreur quand je rentre un nombre comme 12345678912 spécifiant "Is not a valid datetime"...

Et si je modifie le type de la variable dateInput en la changeant en "Double"et le "
StrToDateTime" en "StrToFloat"
, je n'ai plus de message d'erreur mais la valeur reprise dans les Year,month, day etc sont toutes à zéro.

Questions:

<ol>
<li>
Cette fonction (DecodeDateTime) est-elle adaptée à la recherche de mon problème .
</li>
<li>
Faut-il que je cherche à construire un autre raisonnement que les mod et div et adapté à l'emploi du type double ?
</li>
</ol>
Merci d'avoir lu ce message jusqu'ici
a+,
EricStib

7 réponses

cs_Loda Messages postés 814 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 30 juillet 2009 3
25 avril 2007 à 12:48
salut,

bon d'abord:
"Entrer un (grand) nombre"
ouai..., ok un grand nombre.... et il represente quoi? le nb de jour ouvrable? le nombre de jour physique? le nb de seconde? depuis quel date? l'an 0? 1900?

Q1:
Les functions de Delphi fonctionnent très bien et tu peux t'en servir pour ton problème SI ton nombre représente un nb de jour depuis "12/30/1899 12:00 am"

StrToDateTime prend en param un string genre "12/3/2007 12:34" si tu veux lire un nb de jour, utilise strtofloat
(rappeles toi les différences de formats régionaux pour le séparateur décimal!)
(ce'st la cause de ton "not a valide datetime")

Laisse ta var en TDateTime (de toute façon c'est un double derrière)

Q2:
je te rappel que la partie fractionnaire d'un TDateTime représente la proportion d'un jour (voir touche magique: F1)

bon code,

Loda

PS HS: "int64" tu connais?

<hr size="2" width="100%" />Se poser les bonnes questions est le premier pas pour trouver les bonnes réponses.
0
EricStib Messages postés 13 Date d'inscription vendredi 23 février 2007 Statut Membre Dernière intervention 26 avril 2007
25 avril 2007 à 18:12
Bonjour Loda,







Il s'agit d'un exercice tiré d'un livre sur Python. Dans ce langage, je n'avais eu aucune difficulté à résoudre cet exercice
 grâce au typage dynamique des variables. Il s'agit simplement d'un nombre, au choix de l'utilisateur.
Il ne veut rien dire, ce nombre. On part du principe qu' 1an = 365, que les mois sont de 30 jours et qu'il y a 12 mois sur une année.



J'ai voulu reproduire cette exercice en Delphi mais j'ai été limité à la barrière des Integers.



Après lecture de ton messge, j'ai relevé la barrière grâce à Int64 et c'est déjà nettement mieux. (J'ai mis le code ci-dessous pour info).

Je déduis, de ton message, que les fonctions sur les dates ne fonctionnent que si on part sur un nombre valable (ce qui est déjà
pas mal pour la plupart des applications "réelles" !! ).

Je vais essayer quelques essais avec le type TDateTime (et des nombres valables de dates) pour voir comment cela fonctionne.

Un grand merci pour le rappel des Int64 et les infos,
a+
EricStib



p

rocedure TForm1.Calcul;
//transforme un nombre donné par l'utilisateur en son équivalent en
//nombre d'Années, de mois, de jours, d'heures, minutes, secondes.
var
nbreInitial,nbreAnnee,nbreMois,nbreJours,
nbreHeures,nbreMinutes,NbreSecondes, reste : Int64;
begin
{les fonctions mod et div ne sont utilisables que dans la gamme des
valeurs integer !! }
try
RichEdit1.Clear;

{Transforme un nombre entier donné en :
Année, Mois, Jour, Heure, Minutes et secondes}
nbreInitial := StrToInt64(L_EdNbresSecondes.Text);

nbreAnnee := nbreInitial div (365*(24*3600));
reste := nbreInitial mod (365*(24*3600));

nbreMois := reste div (3600*24*30);
reste := reste mod (3600*24*30);

nbreJours := reste div (3600*24);
reste := reste mod (3600*24);

nbreHeures := reste div 3600;
reste := reste mod 3600;

nbreMinutes := reste div 60;
nbreSecondes := reste mod 60;

with RichEdit1.Lines do
begin
Add('Nombres d''années :' + IntToStr(nbreAnnee));
Add('Nombre de mois :' + IntToStr(nbreMois));
Add('Nombre de jours :' + IntToStr(nbreJours));
Add('Nombre d''heures :' + IntToStr(nbreHeures));
Add('Nombre de minutes : ' + IntToStr(nbreMinutes));
Add('Nombre de secondes :' + IntToStr(nbreSecondes));

end;

except
MessageDlg('Dépassement de la limite des integer ! ', mtWarning, [mbOK], 0);
end;
end;
0
japee Messages postés 1727 Date d'inscription vendredi 27 décembre 2002 Statut Modérateur Dernière intervention 6 novembre 2021 8
25 avril 2007 à 23:52
Salut,


EricStib, désolé mais ton algo est faux :

- au départ tu utilises une année de 365 jours,

- pour la suite des calculs tu te bases sur 12 mois de 30 jours,

alors que tu devrais utiliser une année de 360 (12 x 30) jours pour rester cohérent...

J'ai testé ta méthode, elle est effectivement légèrement faussée par endroits.
0
japee Messages postés 1727 Date d'inscription vendredi 27 décembre 2002 Statut Modérateur Dernière intervention 6 novembre 2021 8
26 avril 2007 à 00:12
Je ne sais pas ce que tu veux faire avec ton calcul...

Mais bon, voilà la méthode correcte basée sur des mois de 30 jours :

procedure FormatSeconds(var Ans, Mois, Jours, Heures, Minutes, Secondes: Int64);
begin
  Minutes := Secondes div 60;
  Secondes := Secondes mod 60;
  Heures := Minutes div 60;
  Minutes := Minutes mod 60;
  Jours := Heures div 24;
  Heures := Heures mod 24;
  Mois := Jours div 30;
  Jours := Jours mod 30;
  Ans := Mois div 12;
  Mois := Mois mod 12;
end;

procedure TForm1.Button1Click(Sender: TObject);
var Ans, Mois, Jours, Heures, Minutes, Secondes: Int64;
begin
  Secondes := StrToInt64(L_EdNbresSecondes.Text);
  FormatSeconds(Ans, Mois, Jours, Heures, Minutes, Secondes);
  RichEdit1.Clear;
  with RichEdit1.Lines do
  begin
    Add(IntToStr(Ans));
    Add(IntToStr(Mois));
    Add(IntToStr(Jours));
    Add(IntToStr(Heures));
    Add(IntToStr(Minutes));
    Add(IntToStr(Secondes));
  end;
end;

Tu noteras l'approche différente puisque je pars des secondes pour remonter vers les années.
De cette manière, le résultat est correct.
Quand à la limite du Int64... tu comptes remonter au jurassique ?

Bonne prog'
0

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

Posez votre question
EricStib Messages postés 13 Date d'inscription vendredi 23 février 2007 Statut Membre Dernière intervention 26 avril 2007
26 avril 2007 à 01:00
Bonjour Japee,

Merci pour la réponse. En fait, l'ennoncé du problème était de transformer un nombre
de secondes en années, mois etc... en considérant qu'il y avait 365 jours dans
une année... et j'ai un peu bâclé parce que je me concentrais sur l'emploi du
type Extended... quitte à remonter à la date du big bang :+)

Je vais refaire le programme et, cette fois, en partant d'une date au choix, jusqu'au
début de calendrier Grégorien et illimité vers le futur et voir ce que cela donne en
année, mois, jours etc... pour pouvoir employé la fonction DecodeDateTime :+)

Pour l'info, je suis occupé à refaire les exercices de Swinnen, "Comment programmer
en Python"... et j'essaie d'adapter en langage Delphi... mais les Types de variables
me troublent car cela n'existe pas en Python (les typages des variables sont dynamiques).

Merci pour l'aide et pour l'exemple du code.
Je vais l'analyser à mon aise pour voir ce que cela donne.
a+
EricStib
0
cs_Loda Messages postés 814 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 30 juillet 2009 3
26 avril 2007 à 13:12
re,

ok, c'est un exo. je comprend mieux.

"jusqu'au début du calendrier Grégorien" ah!. ça fait plaisir de voir qu'il y a encore des gens qui font un peu de recherche avant de commencer à coder. (lors d'un labo similaire, je me rappel avoir argumenter contre mon prof  une limite inférieur pour l'année. Il voulais mettre la limite à 0 l'ignorant.)
Mais, en même temps, tu compte pas les année bis. mais tu compte le début du calendrier. ;-)

"les typages des variables sont dynamiques"
sans bien voir de quoi tu parle, tu dois pouvoir simuler ce type de comportement en créant une class avec accesseur. (getValue, asString, setValue(int), setValue(string), ...)
les accesseur pouvant appeler des pointeur de procedure ayant un paramètre variant.

<hr size="2" width="100%" />
sinon, pourquoi ne fait tu pas l'exercice seulement pour les jour/heure/minute/seconde/milli. comme ça c'est "juste" au moins. non?

aussi, tu peux faire l'exo avec des mod/div pour les sec-jour. et pour les mois: des type enum + un tableau "NdJourParMois[TypeEnum] of int"
la règles pour les année bis. est simple: tout les 4ans, -tout les 100ans, + tout les 400ans

bon exo !

Loda
<hr size="2" width="100%" />Se poser les bonnes questions est le premier pas pour trouver les bonnes réponses.
0
cs_Loda Messages postés 814 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 30 juillet 2009 3
26 avril 2007 à 13:14
...

"les accesseur pouvant appeler des pointeur de procedure ayant un paramètre variant."
lire
"les accesseur pouvant appeler des pointeur de procedure ayant un paramètre variable (var)."

Loda
<hr size="2" width="100%" />Se poser les bonnes questions est le premier pas pour trouver les bonnes réponses.
0
Rejoignez-nous