Autor |
Beitrag |
midan23
      
Beiträge: 48
Win XP, Mac OS X, Linux
D6 Pers, XCode 2.1, Python
|
Verfasst: So 08.08.04 19:48
In einem meiner Programme habe ich mehrere tDateTime-Komponenten um Ein- und Ausschaltzeiten eingeben zu können. Dabei soll die Ausschaltzeit immer grösser sein als die Einschaltzeit.
Und genau das funktioniert nicht ... Hier ein Beispiel :
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68:
| object Test: TTest Left = 217 Top = 106 Width = 153 Height = 94 Caption = 'Test' Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] OldCreateOrder = False PixelsPerInch = 96 TextHeight = 13 object lEin: TLabel Left = 8 Top = 8 Width = 73 Height = 21 Alignment = taCenter AutoSize = False Caption = 'Einschaltzeit' Layout = tlCenter end object lAus: TLabel Left = 8 Top = 40 Width = 73 Height = 21 Alignment = taCenter AutoSize = False Caption = 'Ausschaltzeit' Layout = tlCenter end object tpEin: TDateTimePicker Left = 88 Top = 8 Width = 49 Height = 21 CalAlignment = dtaLeft Date = 38207 Format = 'HH:mm' Time = 38207 DateFormat = dfShort DateMode = dmComboBox Kind = dtkTime ParseInput = False TabOrder = 0 OnChange = tpChange end object tpAus: TDateTimePicker Left = 88 Top = 40 Width = 49 Height = 21 CalAlignment = dtaLeft Date = 38207.0006944444 Format = 'HH:mm' Time = 38207.0006944444 DateFormat = dfShort DateMode = dmComboBox Kind = dtkTime ParseInput = False TabOrder = 1 OnChange = tpChange end end |
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, StdCtrls;
type TTest = class(TForm) lEin: TLabel; lAus: TLabel; tpEin: TDateTimePicker; tpAus: TDateTimePicker; procedure tpChange(Sender: TObject); private public end;
var Test: TTest;
implementation
{$R *.dfm}
uses dateUtils;
procedure TTest.tpChange(Sender: TObject); begin if tpAus.Time <= tpEin.Time then tpAus.Time := incMinute(tpEin.Time); end;
end. |
Weiss jemand, woran das liegen könnte und wie man das Problem beheben könnte ?
|
|
midan23 
      
Beiträge: 48
Win XP, Mac OS X, Linux
D6 Pers, XCode 2.1, Python
|
Verfasst: Mo 09.08.04 08:08
Mittlerweile hab ich nachgeforscht ...
tDateTimePicker verwendet zum speichern des Datums und der Uhrzeit eine Variable vom Typ tDateTime, welcher als double definiert ist.
Der Teil vor dem Komma ist die Anzahl Tage seit dem 30.12.1899, während der Teil nach dem Komma die Uhrzeit enthält (sozusagen als Bruchteil des Tages).
Das Problem mit dem ich seit ein paar Tgaen kämpfe ist also einfach nur ein Rundungsfehler, der bei Fliesskomazahlen unvermeidbar ist ...
Ich hab im Internet nachgeforscht, scheinbar gibt es keine brauchbare Alternative zur Zeiteingabe ... das schreit doch schon fast nach einer neuen Komponente ...
|
|
Klabautermann
      

Beiträge: 6366
Erhaltene Danke: 60
Windows 7, Ubuntu
Delphi 7 Prof.
|
Verfasst: Mo 09.08.04 08:15
Wie gering sind denn deine Zeituntereschiede? tDateTime kommt noch problemlos mit dem Millisekundenbereich zurecht, Probleme solltest du erst bekommen, wenn du drunter liegst.
Ich kann mir nicht vorstellen, dass es dadran liegt, wie genau äußert sich denn das Problem?
Gruß
Klabautermann
|
|
midan23 
      
Beiträge: 48
Win XP, Mac OS X, Linux
D6 Pers, XCode 2.1, Python
|
Verfasst: Mo 09.08.04 08:59
Wenn man in meinem Programm die Minuten der Startzeit erhöht, bekommt man folgende Werte :
Start - Ende
00:00 - 00:01
00:01 - 00:02
00:02 - 00:02 *
00:03 - 00:04
00:04 - 00:05
00:05 - 00:05 *
00:06 - 00:07
00:07 - 00:08
00:08 - 00:09
00:09 - 00:09 *
Alle mit * markierten Zeilen sollten eigentlich nicht vorkommen ...
Wenn man darüber nachdenkt, gibt es nur vier mögliche Fehlerquellen :
1) Ein Fehler in meinem Sourcecode (Der Fehler ist mit meinem Beispiel-Programm oben nachvollziehbar ...)
2) Rundungsfehler bei Fiesskommazahlen
3) Fehler in "incMinute"
4) Fehler in tDateTimePicker (eher unwahrscheinlich)
|
|
Klabautermann
      

Beiträge: 6366
Erhaltene Danke: 60
Windows 7, Ubuntu
Delphi 7 Prof.
|
Verfasst: Mo 09.08.04 10:29
Hallo,
ja du hast recht, der Effekt liegt an einem Rundungsfehler oder daran, das der DateTime Picker den Minutenwertanders erhöht als IncMinute.
Ich konnte das Problem nicht rekonstruieren, wenn ich selbstgeschriebene Funktion IncAnotherMinute verwende. ICh hoffe diese ist ein akzeptabler Workaround.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| function IncAnotherMinute(aTime: tTime): tTime; var aMinute, ahour, aSecond, amSecond : Word; begin DecodeTime(aTime, aHour, aMinute, aSecond, amSecond); if (aMinute = 59) then begin aMinute := 0; if aHour = 23 then aHour := 0 else inc(aHour); end else inc(aMinute); Result := EncodeTime(aHour, aMinute, aSecond, amSecond); end; |
Gruß
Klabautermann
|
|
midan23 
      
Beiträge: 48
Win XP, Mac OS X, Linux
D6 Pers, XCode 2.1, Python
|
Verfasst: Mo 09.08.04 12:03
Funktioniert ! wie eine Eins ! Danke ...
Ich dachte schon, ich müsste dafür eine eigene Komponente entwerfen ...
Hatte mir sogar schon konkrete Gedanken darüber gemacht :
- Speichern der Zeit in getrennten Variablen für Stunden, Minuten und Sekunden
- Möglichkeit die Zeit als "Sekunden seit Mitternacht" zu setzten und zu erhalten
- Erhöhen bzw. erniedrigen um x Stunden, Minuten oder Sekunden unter berücksichtigung von Minimal- bzw Maximal-Werten
- Funktion um die Zeit als Zeichenkette zu erhalten, wobei zwischen 12 und 24-Stundenformat gewählt werden kann. Man kann die Zeichenkette auch mit oder ohne Sekunden erhalten.
Würde ich mir alles zutrauen ... bis auf eins :
Wie kann ich sicherstellen, das der Benutzer eine gültige Zeit eingibt ?
Hab schon versucht, eine eigene Komponente von tCustomEdit bzw tCustomMaskEdit abzuleiten aber die Eingabe auf gültige Werte einzuschränken ist mir noch nicht gelungen ...
|
|
Klabautermann
      

Beiträge: 6366
Erhaltene Danke: 60
Windows 7, Ubuntu
Delphi 7 Prof.
|
Verfasst: Mo 09.08.04 12:18
Hi,
wenn es mit der Funktion nicht geklappt hätte, währe mein nächster Schritt gewesen die IF abfrage ein wenig unpräziser zu machen. Denn diese hat ja nciht gegriffen, da du ja sonst mindesten 59,x Sekunden differenz haben müstest, du hast aber scheinbar -0,x Sekunden differenz. Eine IF abfrage dieser Art:
Delphi-Quelltext 1:
| if (tpAus.Time <= tpEin.Time + NeViertelSekundeOderSo) then |
sollte das Problem genau so lösen.
Gruß
Klabautermann
PS: Wenn dein Problem gelöst ist, kannst du den Status (des ersten Postings) entsprechend setzen.
|
|
Uli Schoch
      
Beiträge: 81
|
Verfasst: Mo 09.08.04 15:45
Hi
Mach doch einfach
Quelltext 1: 2:
| if tpAus.Time <= tpEin.Time then tpAus.Time := tpEin.Time + 1/24/60; |
So addierst du eine Minute = 1 Tag / 24 h pro Tag / 60 Minute pro Stunde
Gruss
Uli
|
|
Klabautermann
      

Beiträge: 6366
Erhaltene Danke: 60
Windows 7, Ubuntu
Delphi 7 Prof.
|
Verfasst: Mo 09.08.04 16:43
Hi,
Uli Schoch hat folgendes geschrieben: | So addierst du eine Minute = 1 Tag / 24 h pro Tag / 60 Minute pro Stunde |
was wieder zu rundungsfehlern führen kann, welche das Problem ja erst verursachten.
Gruß
Klabautermann
|
|
midan23 
      
Beiträge: 48
Win XP, Mac OS X, Linux
D6 Pers, XCode 2.1, Python
|
Verfasst: Mo 09.08.04 18:55
Die Funktion löst das Problem in diesem Fall, aber bei Fliesskommazahlen kann man Rundungsfehler nie ganz ausschliessen ...
Ich denke, ich nehme die Funktion als vorläufige Lösung und entwickle eine Komponente ... da gibt es dann keine Rundungsfehler mehr ...
Weiterer Vorteil : Es wird meine erste Komponente ... also für mich eine gute Gelegenheit was neues zu lernen ...
|
|
|