Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Komme nicht weiter mit Zeitvergleichen? (https://www.delphipraxis.net/141933-komme-nicht-weiter-mit-zeitvergleichen.html)

AlexII 19. Okt 2009 12:12


Komme nicht weiter mit Zeitvergleichen?
 
Hallo,
ich möchte einen Wecker schreibe und hab folgendes geschrieben:

Delphi-Quellcode:
procedure TForm4.FormShow(Sender: TObject);
begin
DateTimePicker2.Time:=Now;
end;

procedure TForm4.Timer1Timer(Sender: TObject);
begin
if DateTimePicker2.Time=Now then ShowMessage('Ok');
end;
Die if Abfrage funktioniert komischerweise nicht, verstehe nicht wieso, ist doch alles richtig geschrieben. :wall: Timer.Interval :=1 sek. Wer weiß da weiter? Danke!

Gausi 19. Okt 2009 12:18

Re: Komme nicht weiter mit Zeitvergleichen?
 
Der Wert von Now ist genauer als der Wert, den du angibst. 15.42 Uhr ist halt nicht derselbe Zeitpunkt wie 15.42 Uhr, 13 Sekunden und 123 Millisekunden.

Außerdem: TDatetime ist ein Float-Typ - die sollte man generell nicht auf Gleichheit überprüfen.

AlexII 19. Okt 2009 12:22

Re: Komme nicht weiter mit Zeitvergleichen?
 
Also
Delphi-Quellcode:
DateTimePicker2.Time
zeigt auch Sekunden an.... hm... und Timer vergleicht auch Millisekunden :gruebel: ah..jah...
Wie vergleicht man dann am besten eine Uhrzeit? Auch so, dass es auf Fremdsprachwindows läuft. :gruebel:

Sir Rufo 19. Okt 2009 12:24

Re: Komme nicht weiter mit Zeitvergleichen?
 
Und wenn man etwas nicht versteht, dann gibt man sich die Werte mal in einer Memo aus und schaut, ob der Vergleich wirklich passen könnte
Delphi-Quellcode:
procedure TForm4.Timer1Timer(Sender: TObject);
var
  Vergleich : TDateTime;
begin
  Vergleich := now; // Merken, weil now ja weiter läuft!!!
  Memo1.Lines.Add( Format( 'DateTimePicker: %s Now: %s', [ FloatToStr( DateTimePicker2.Time ), FloatToStr( Vergleich ) ] );
  if ( DateTimePicker2.Time = Vergleich ) then ShowMessage('Ok');
end;

Sharky 19. Okt 2009 12:24

Re: Komme nicht weiter mit Zeitvergleichen?
 
Zitat:

Zitat von AlexII
... Wie vergleicht man dann am besten eine Uhrzeit? ...

In diesem Fall einfach mit >= vergleichen.

Luckie 19. Okt 2009 12:25

Re: Komme nicht weiter mit Zeitvergleichen?
 
Zitat:

Zitat von Sharky
Zitat:

Zitat von AlexII
... Wie vergleicht man dann am besten eine Uhrzeit? ...

In diesem Fall einfach mit >= vergleichen.

Plus einem Deltawert, sonst stimmt der Vergleich 23 Stunden und 59 Minuten. ;)

AlexII 19. Okt 2009 12:33

Re: Komme nicht weiter mit Zeitvergleichen?
 
Zitat:

Zitat von Sir Rufo
Und wenn man etwas nicht versteht, dann gibt man sich die Werte mal in einer Memo aus und schaut, ob der Vergleich wirklich passen könnte
Delphi-Quellcode:
procedure TForm4.Timer1Timer(Sender: TObject);
var
  Vergleich : TDateTime;
begin
  Vergleich := now; // Merken, weil now ja weiter läuft!!!
  Memo1.Lines.Add( Format( 'DateTimePicker: %s Now: %s', [ FloatToStr( DateTimePicker2.Time ), FloatToStr( Vergleich ) ] );
  if ( DateTimePicker2.Time = Vergleich ) then ShowMessage('Ok');
end;

Now muss ja auch weiterlaufen, DateTimePicker2.Time bleibt konstant eingestellt und vergleichen tust du genauso wie ich, was genauso nicht funktioniert. :pale:

TheFrog 19. Okt 2009 12:41

Re: Komme nicht weiter mit Zeitvergleichen?
 
Vielleicht kommst Du ja mit der Delphi-Procedure DecodeTime() weiter. Diese zerlegt Dir den Zeitwert in Stunden, Minuten, ..., welche Du dann vergleichen kannst.

Hans.

Sir Rufo 19. Okt 2009 12:44

Re: Komme nicht weiter mit Zeitvergleichen?
 
Zitat:

Zitat von AlexII
Zitat:

Zitat von Sir Rufo
Und wenn man etwas nicht versteht, dann gibt man sich die Werte mal in einer Memo aus und schaut, ob der Vergleich wirklich passen könnte
Delphi-Quellcode:
procedure TForm4.Timer1Timer(Sender: TObject);
var
  Vergleich : TDateTime;
begin
  Vergleich := now; // Merken, weil now ja weiter läuft!!!
  Memo1.Lines.Add( Format( 'DateTimePicker: %s Now: %s', [ FloatToStr( DateTimePicker2.Time ), FloatToStr( Vergleich ) ] );
  if ( DateTimePicker2.Time = Vergleich ) then ShowMessage('Ok');
end;

Now muss ja auch weiterlaufen, DateTimePicker2.Time bleibt konstant eingestellt und vergleichen tust du genauso wie ich, was genauso nicht funktioniert. :pale:

Du sollst Dir ja auch die Werte !!ansehen!! und dann wirst du !!sehen!! warum das nicht funktioniert!!!
Und der Wert von Now wird sich deshalb gemerkt, damit auch das ausgegeben wird, was danach dann auch verglichen wird!

Sherlock 19. Okt 2009 12:47

Re: Komme nicht weiter mit Zeitvergleichen?
 
OK, weils keiner wirklich erklärt hat, versuch ich mich mal daran:

Wissenswerte Voraussetzungen:
  • Ein DateTime erfasst auch Millisekunden.
  • Now ist natürlich auch auf die Millisekunde genau.
  • Der Timer ist nicht Millisekunden genau, da windows keine Echtzeitsystem ist.

Wenn Du also (millisekunden-)genaue Gleichheit prüfen möchtest ist es extrem wahrscheinlich, daß Du nicht die korrekte Millisekunde erwischst. Deshalb soltlest Du vielleicht nur Sekunden- oder Minutengenau prüfen. Wie Du das anstellst überlass ich mal Deiner Phantasie.

Sherlock

AlexII 19. Okt 2009 12:52

Re: Komme nicht weiter mit Zeitvergleichen?
 
Ich verstehe jetzt die Logik nicht wie Delphi mit der Zeit umgeht.

Das hier funkt nicht:
Delphi-Quellcode:
Label2.Caption:=TimeToStr(Now);
Label3.Caption:=TimeToStr(DateTimePicker2.Time);
if Now=DateTimePicker2.Time then showmessage('ja');
aber das:
Delphi-Quellcode:
Label2.Caption:=TimeToStr(Now);
Label3.Caption:=TimeToStr(DateTimePicker2.Time);
if Label2.Caption=Label3.Caption then showmessage('ja');
obwohl das ja gleich ist. :roteyes:

AlexII 19. Okt 2009 12:55

Re: Komme nicht weiter mit Zeitvergleichen?
 
Zitat:

Zitat von Sherlock
OK, weils keiner wirklich erklärt hat, versuch ich mich mal daran:

Wissenswerte Voraussetzungen:
  • Ein DateTime erfasst auch Millisekunden.
  • Now ist natürlich auch auf die Millisekunde genau.
  • Der Timer ist nicht Millisekunden genau, da windows keine Echtzeitsystem ist.

Wenn Du also (millisekunden-)genaue Gleichheit prüfen möchtest ist es extrem wahrscheinlich, daß Du nicht die korrekte Millisekunde erwischst. Deshalb soltlest Du vielleicht nur Sekunden- oder Minutengenau prüfen. Wie Du das anstellst überlass ich mal Deiner Phantasie.

Sherlock

Wow das nenne ich fachmännisch. :thumb:

Tyrael Y. 19. Okt 2009 12:55

Re: Komme nicht weiter mit Zeitvergleichen?
 
Zitat:

Zitat von Luckie
Plus einem Deltawert, sonst stimmt der Vergleich 23 Stunden und 59 Minuten. ;)

Wozu das?

Wenn man zwei TDateTime hat und mit größer gleich abfragt stimmt, die Abfrage in jedem Fall.
Das wichtige ist bei reiner Uhrzeitabfrage, daß man auch NUR die Uhrzeit vergleicht.

Delphi-Quellcode:
procedure TForm4.FormShow(Sender: TObject);
begin
  DateTimePicker2.Time := TimeOf(Now())
end;

procedure TForm4.Timer1Timer(Sender: TObject);
begin
   if TimeOf(Now()) >= DateTimePicker2.Time then
     ShowMessage('Ok');
end;
Habs nicht getestet, aber sollte so richtig sein.

Sir Rufo 19. Okt 2009 12:56

Re: Komme nicht weiter mit Zeitvergleichen?
 
Zitat:

Zitat von AlexII
Ich verstehe jetzt die Logik nicht wie Delphi mit der Zeit umgeht.

Das hier funkt nicht:
Delphi-Quellcode:
Label2.Caption:=TimeToStr(Now);
Label3.Caption:=TimeToStr(DateTimePicker2.Time);
if Now=DateTimePicker2.Time then showmessage('ja');
aber das:
Delphi-Quellcode:
Label2.Caption:=TimeToStr(Now);
Label3.Caption:=TimeToStr(DateTimePicker2.Time);
if Label2.Caption=Label3.Caption then showmessage('ja');
obwohl das ja gleich ist. :roteyes:

Nein, ist es nicht!

In Now steht z.B. 2009-10-19 13:56:25.123 => TimeToStr(Now) => 13:56:25 !!!!!!

Wenn Du diesen Code (auf einen Button legen) ausführst ( auf der Form musst du natürlich ein MemoFeld mit Namen Memo1 haben! )
Delphi-Quellcode:
begin
  Memo1.Lines.Add( FloatToStr( Now ) );
  Label1.Caption := TimeToStr( Now );
  Memo1.Lines.Add( FloatToStr( Now ) );
  Label2.Caption := TimeToStr( now );
  Memo1.Lines.Add( FloatToStr( Now ) );
end;
Dann erscheint im Memo1 folgende Ausgabe:
Code:
40105,5863273264
40105,5863273611
40105,5863273727
Die Interpretation überlasse ich Dir!

AlexII 19. Okt 2009 13:04

Re: Komme nicht weiter mit Zeitvergleichen?
 
Zitat:

Undefinierter Bezeichner: TimeOf
Was soll den in die Uses rein? :gruebel:

Tyrael Y. 19. Okt 2009 13:05

Re: Komme nicht weiter mit Zeitvergleichen?
 
Delphi-Quellcode:
uses DateUtils;

hoika 19. Okt 2009 13:09

Re: Komme nicht weiter mit Zeitvergleichen?
 
Hallo,

noch mal zu deinem Code.

Delphi-Quellcode:
Label2.Caption:=TimeToStr(Now);
Label3.Caption:=TimeToStr(DateTimePicker2.Time);
if Now=DateTimePicker2.Time then showmessage('ja');
In Zeile 3 ist Now schon wieder etwas weiter
als in Zeile 1.

Wenn es wirklich nur ein Wecker sein soll,
der genau einmal weckt, vergleiche mit >=

Delphi-Quellcode:
Label1.Caption:= TimeToStr('15:00'); // wir wollen 15:00 wecken

procedure Timer1OnTimer
begin
  if Now>=StrToTime(Label1.Caption) then
  begin
    ShowMessage('klingellllll');
    Timer1.Enabled:= False;
  end;
end;

Heiko

AlexII 19. Okt 2009 13:09

Re: Komme nicht weiter mit Zeitvergleichen?
 
Zitat:

Zitat von Tyrael Y.

Delphi-Quellcode:
procedure TForm4.FormShow(Sender: TObject);
begin
  DateTimePicker2.Time := TimeOf(Now())
end;

procedure TForm4.Timer1Timer(Sender: TObject);
begin
   if TimeOf(Now()) >= DateTimePicker2.Time then
     ShowMessage('Ok');
end;

Funkt auch nicht :wall:

Sir Rufo 19. Okt 2009 13:11

Re: Komme nicht weiter mit Zeitvergleichen?
 
Zitat:

Zitat von hoika
Delphi-Quellcode:
if Now>=StrToTime(Label1.Caption) then

Öh, der Vergleich ist aber immer True!
StrToTime( '15:00' ) => 0.625
Now ist aber irgendwie immer > 1.0 (aktuell > 40105.0)

AlexII 19. Okt 2009 13:16

Re: Komme nicht weiter mit Zeitvergleichen?
 
Wusste gar nicht, dass einfach zwei Zeiten zu vergleichen so kompliziert ist. :lol:

Sir Rufo 19. Okt 2009 13:18

Re: Komme nicht weiter mit Zeitvergleichen?
 
Zitat:

Zitat von AlexII
Wusste gar nicht, dass einfach zwei Zeiten zu vergleichen so kompliziert ist. :lol:

Ist es ja auch nicht ... aber es gibt halt Milliarden falsche Wege und nur wenig richtige Wege.

Um auf das kleine Beispiel mit dem Wecker zu kommen, das geht so:
Delphi-Quellcode:
procedure TForm1.Timer1Timer(Sender:TObject);
begin
  if Frac( Now ) >= StrToTime( '15:00' ) then
    begin
      Timer1.Enabled := False;
      ShowMessage( 'Jetzt sollte ich Dich wecken!' );
    end;
end;

Tyrael Y. 19. Okt 2009 13:20

Re: Komme nicht weiter mit Zeitvergleichen?
 
Ich habs grad getestet, mein Code funktioniert.

WICHTIG!
Beim TDateTimePicker die Eiegnschaft Date im ObjektInspektor löschen.
Dann wird dort 30.12.1899 automatisch eingetragen und dann passt es.

Edit:
Zum setzen der Zeit für den DateTimePicker beim FormShow ist suboptimal.
FormShow wird bei jedem anzeigen aufgerufen.
D.h. du minimierst das Fenster und holst es wieder -> FormShow

mleyen 19. Okt 2009 13:20

Re: Komme nicht weiter mit Zeitvergleichen?
 
Zitat:

Zitat von Tyrael Y.
Zitat:

Zitat von Luckie
Plus einem Deltawert, sonst stimmt der Vergleich 23 Stunden und 59 Minuten. ;)

Wozu das?

Weil der Wecker dann 24/7 klingelt. :zwinker:

@AlexII:
Eigentlich ist das gar nicht schwer, man muss nur einmal das Problem erkennen.

Du vergleichst 2 Werte mit unterschiedlicher Genauigkeit.
Um diese trotzdem auf "Gleichheit" prüfen zu können, musst du ein bisschen ungenauer werden.
In deinem Fall musst du dazu eine zeitrange einbauen.
Also einen bestimmten Zeitintervall, indem gesagt wird, die Zeit stimmt mit der anderen überein.

Als Beispiel mal Floatwerte:
Delphi-Quellcode:
procedure TBluppForm.button1Click(Sender: TObject);

  function SingleEquals(const AVal1, AVal2: Single; const Precision: Single = 1.0): Boolean;
  begin
    Result :=
      (AVal2 > AVal1 - Precision) and
      (AVal2 < AVal1 + Precision)
  end;

begin
  if SingleEquals(2.0, 3.2) then
    MessageDlg('1. Equals', mtInformation, [mbOK], 0);
  if SingleEquals(2.0, 3.2, 1.5) then
    MessageDlg('2. Equals', mtInformation, [mbOK], 0);
end;

Ich hoffe das Problem ist jetzt verständlicher geworden :)

AlexII 19. Okt 2009 13:30

Re: Komme nicht weiter mit Zeitvergleichen?
 
Zitat:

Zitat von Tyrael Y.
Zum setzen der Zeit für den DateTimePicker beim FormShow ist suboptimal.

Was heißt bei dir suboptimal?

Und wieso vergleichst du mit >= und nicht einfach = ? :gruebel:

Sir Rufo 19. Okt 2009 13:34

Re: Komme nicht weiter mit Zeitvergleichen?
 
Zitat:

Zitat von AlexII
Und wieso vergleichst du mit >= und nicht einfach = ? :gruebel:

Liest du auch, was hier in dem Thread geschrieben steht?

Es gibt mehrere Antworten, die sich genau darauf beziehen.

DeddyH 19. Okt 2009 13:35

Re: Komme nicht weiter mit Zeitvergleichen?
 
Nochmal: man vergleicht keine 2 Double-Werte mit =, da die Wahrscheinlichkeit gering ist, dass sie wirklich exakt übereinstimmen.

AlexII 19. Okt 2009 13:36

Re: Komme nicht weiter mit Zeitvergleichen?
 
Zitat:

Zitat von Sir Rufo
Zitat:

Zitat von AlexII
Und wieso vergleichst du mit >= und nicht einfach = ? :gruebel:

Liest du auch, was hier in dem Thread geschrieben steht?

Es gibt mehrere Antworten, die sich genau darauf beziehen.

Wenn man bei 25 Posts 30 verschiedene Meinungen hört kommt man durcheinander. :roteyes:

DeddyH 19. Okt 2009 13:39

Re: Komme nicht weiter mit Zeitvergleichen?
 
Wirf doch einfach mal einen Blick in die Unit DateUtils, da steht viel Nützliches für Deine Zwecke drin.

AlexII 19. Okt 2009 13:40

Re: Komme nicht weiter mit Zeitvergleichen?
 
Zitat:

Zitat von DeddyH
Nochmal: man vergleicht keine 2 Double-Werte mit =, da die Wahrscheinlichkeit gering ist, dass sie wirklich exakt übereinstimmen.

Ich muss das leider genau haben, also = :gruebel: Dann muss ich wohl die Sekunden streichen.

AlexII 19. Okt 2009 13:41

Re: Komme nicht weiter mit Zeitvergleichen?
 
Zitat:

Zitat von DeddyH
Wirf doch einfach mal einen Blick in die Unit DateUtils, da steht viel Nützliches für Deine Zwecke drin.

Wo kriegt man sie her? :shock:

Sharky 19. Okt 2009 13:44

Re: Komme nicht weiter mit Zeitvergleichen?
 
Zitat:

Zitat von AlexII
Ich muss das leider genau haben, also = :gruebel: Dann muss ich wohl die Sekunden streichen.

Nicht die Sekunden! Die Millisekunden.
Einfacher Ablauf:

* Speichere in Einer Variablen (TDateTime) wann der "Termin" ist.
* Lasse alle 250 ms deinen Timer Event starten
* Extrahiere Dir aus Now Stunden: Minuten: Sekunden.
* Vergleiche das mit deiner Variable.

Frankfurtoder 19. Okt 2009 13:47

Re: Komme nicht weiter mit Zeitvergleichen?
 
Zitat:

Zitat von AlexII
Wo kriegt man sie her? :shock:

Ist seit D6 dabei und vorher waren solche Funktionen in System meine ich. Du hast leider keine Delphi Version angegeben.

Sir Rufo 19. Okt 2009 13:47

Re: Komme nicht weiter mit Zeitvergleichen?
 
Zitat:

Zitat von AlexII
Zitat:

Zitat von DeddyH
Wirf doch einfach mal einen Blick in die Unit DateUtils, da steht viel Nützliches für Deine Zwecke drin.

Wo kriegt man sie her? :shock:

also ich geb hier jetzt auf ... :roll:

Medium 19. Okt 2009 13:50

Re: Komme nicht weiter mit Zeitvergleichen?
 
Ich brech echt zusammen... so schwierig ist des doch nu echt nicht. Du wirst wohl kaum einen Wecker auf die Millisekunde genau brauchen!? Lass einen Timer halt jede Sekunde prüfen ob "now" größer-gleich dem Weckzeitpunkt ist, und im Timer dann klingeln an, und Timer aus. Bams. Spätestens mit einer Sekunde und ner Hand voll Millisekunden Verspätung klingelt dein Wecker, und zwar genau ein Mal bis er wieder eingeschaltet wird.

Wenn du es nicht verstehen WILLST, nimm doch bitte einfach erstmal hin, dass Gleichheit bei Fließkommawerten fast immer ein Glücksspiel ist, dass man gerade beim Arbeiten mit Zeitwerten praktisch nicht gewinnen kann. Du wirst in der Praxis nie genau die eine Millisekunde mit deinem Timer treffen, völlig egal wie kurz du das Intervall stellst. Das liegt in der "Natur" der Sache.

Und falls noch nicht ganz klar ist warum Datums-/Zeitwerte Fließkommawerte sind: TDateTime = Double; So ist es definiert.


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:08 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz