Autor Beitrag
midan23
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 48

Win XP, Mac OS X, Linux
D6 Pers, XCode 2.1, Python
BeitragVerfasst: 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 :
ausblenden volle Höhe Delphi-Quelltext
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

ausblenden volle Höhe Delphi-Quelltext
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
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 48

Win XP, Mac OS X, Linux
D6 Pers, XCode 2.1, Python
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Veteran
Beiträge: 6366
Erhaltene Danke: 60

Windows 7, Ubuntu
Delphi 7 Prof.
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 48

Win XP, Mac OS X, Linux
D6 Pers, XCode 2.1, Python
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Veteran
Beiträge: 6366
Erhaltene Danke: 60

Windows 7, Ubuntu
Delphi 7 Prof.
BeitragVerfasst: 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.

ausblenden 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 = 59then begin
    aMinute := 0;
    if aHour = 23 then
      aHour := 0
    else
      inc(aHour);
  end
  else
    inc(aMinute);
  Result := EncodeTime(aHour, aMinute, aSecond, amSecond);
end// IncAnotherMinute


Gruß
Klabautermann
midan23 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 48

Win XP, Mac OS X, Linux
D6 Pers, XCode 2.1, Python
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Veteran
Beiträge: 6366
Erhaltene Danke: 60

Windows 7, Ubuntu
Delphi 7 Prof.
BeitragVerfasst: 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:

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 81



BeitragVerfasst: Mo 09.08.04 15:45 
Hi
Mach doch einfach

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Veteran
Beiträge: 6366
Erhaltene Danke: 60

Windows 7, Ubuntu
Delphi 7 Prof.
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 48

Win XP, Mac OS X, Linux
D6 Pers, XCode 2.1, Python
BeitragVerfasst: 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 ...