Entwickler-Ecke

Sonstiges (Delphi) - Ungültiges Datum abfangen


donarac - So 12.11.06 16:32
Titel: Ungültiges Datum abfangen
Hallo in die Runde,

ich möchte in einem (CountDown)Programm über drei ComboBoxen anbieten, ein Datum zusammen zu setzen. Anschließend wandle ich die drei Strings mit EncodeDate in eine Variable des Typs TDateTime um, damit ich mit ihr rechnen kann.
Leider ist es aber auch möglich, ein falsches Datum (z.B. 30.02.20xx) einzugeben - dann meckert jedoch sofort das Programm
Zitat:
...'Ungültiges Argument für die Datumskodierung'...
und es ist nicht möglich, den Wert zu korrigieren.

Da die "Funktion" in der Timer-Prozedur durchgeführt wird, ist es ziemlich nervig.

Ich habe auch schon versucht, die Umwandlung in eine Try-Abfrage zu setzen, aber das hat auch nicht funktioniert.

Kann mir dazu Jemand eine Lösung posten?

P.S. Ich benutze noch Delphi3, sodass mir die neuen Datums-Utils nicht zur Verfügung stehen.


mkinzler - So 12.11.06 16:34

-TDateTimePicker
-TryStrToDate statt StrToDate


donarac - Di 14.11.06 02:15

Zitat:
-TDateTimePicker
-TryStrToDate statt StrToDate

Kennt mein Delphi nicht!

Zur Verdeutlichung hier der kritische Code:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
procedure TfrmCountDown.Timer1Timer(Sender: TObject);
begin
  dat := Now;
  Timer1.Enabled := true;
...
MyDate := EncodeDate(StrToInt(strJahrZiel), StrToInt(strMonatZiel), StrToInt(strTagZiel));

intTage := round(MyDate- dat)+1;
...

Die str...-Variabeln enthalten z.B. die Werte '2006', '12', '24' - damit funzt es. :-) Bei '2007', '02' und '29' fägt der Tanz an. :-(


hansa - Di 14.11.06 03:23

Delphi 3 kenne ich jetzt nicht. -> Bitte updaten ! :lol: Alternative : nachrüsten mit TurboPower. Müßte Orpheus sein. Da sind zumindest Uhren dabei. Such selber mal auf SourceForge genauer. Eventuell sind die fehlenden Routinen nicht in Orpheus, sondern in irgendeinem System-Paket von Turbopower. Bei D3 lohnt sich die Nachrüstung wohl schnell.


mkinzler - Di 14.11.06 07:51

Wenn dein Delphi kein Try<Typ>To<Typ> kennt kannst du die Konvertierung ja noch in try..except einbetten.


Delete - So 19.11.06 13:57

hallo normal erst die fehler abfangen (nicht zu den fehlern kommen lassen) und dann die operation durchführen. das try... konzept ist nur für punkte welche nicht vorhersehbar sind oder in anderen objekten passieren...

hier bei deinem problem bieten sich mehrere möglichkeiten an...

a) erst den ttimer starten, wenn das datum ok ist, nicht vorher, wie in deinem code ausschnitt.

b) das datum bei der eingabe validieren... z.b. nur anzeigekomponenten, welche mit tasten einzustellen sind.. und die automatisch unmögliche tage wie den "79. dezember 49095" vermeiden

c) wenn ein ungültiges datum festgestellt wird, auf das nächstmögliche gültige datum gehen.. und dann die eingabe wiederholen lassen

d) wenn das so weit in ordnung ist, datum konvertieren und dann auf plausi prüfen... ggf. neue informationen vom anwender einholen.. erst wenn alles ok, dann den countdown starten..

das andere vorgeschlagene sind krücken, nur der tdatetimepicker ist sinnvoll, kannst dir aber auch selber basteln, siehe b)

<HTH>


Lannes - So 19.11.06 14:47

Hallo,
user profile icondonarac hat folgendes geschrieben:
Zitat:
-TDateTimePicker

Kennt mein Delphi nicht!
D3 :arrow: schau mal bei /Win32\ in der Komponenten-Palette.


VaNaTiC - So 19.11.06 20:31

Prinzipiell hat Grenzgaenger recht. Man sollte mit einem vertretbarem Aufwand invalide Eingaben schon während der Eingabe prüfen. Leider ist das meiner Meinung nach ohne TryStrToDate bei drei einzelnen strings z.Bsp. für den 29.02.2007 nicht mehr vertretbar.
Ich würde an Deiner Stelle Dein OnTimer-Event um ein try-except erweitern.
Zum Beispiel so:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
procedure TfrmCountDown.Timer1Timer(Sender: TObject); 
begin
  Timer1.Enabled := False;
  try
    dat := Now; 
    ... 
    MyDate := EncodeDate(StrToInt(strJahrZiel), StrToInt(strMonatZiel), StrToInt(strTagZiel));
    intTage := round(MyDate- dat)+1
    ...
  except
    intTage := -1// eventuell zur Fehlerrückmeldung
  end;

  // Den Timer solltest Du auch wieder anschalten, oder wird das woanders gestartet?
  // Dann verstehe ich aber das TimerEnabled in Deinem Beispielcode nicht
  Timer1.Enabled := True;
end;