![]() |
Komme nicht weiter mit Zeitvergleichen?
Hallo,
ich möchte einen Wecker schreibe und hab folgendes geschrieben:
Delphi-Quellcode:
Die if Abfrage funktioniert komischerweise nicht, verstehe nicht wieso, ist doch alles richtig geschrieben. :wall: Timer.Interval :=1 sek. Wer weiß da weiter? Danke!
procedure TForm4.FormShow(Sender: TObject);
begin DateTimePicker2.Time:=Now; end; procedure TForm4.Timer1Timer(Sender: TObject); begin if DateTimePicker2.Time=Now then ShowMessage('Ok'); end; |
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. |
Re: Komme nicht weiter mit Zeitvergleichen?
Also
Delphi-Quellcode:
zeigt auch Sekunden an.... hm... und Timer vergleicht auch Millisekunden :gruebel: ah..jah...
DateTimePicker2.Time
Wie vergleicht man dann am besten eine Uhrzeit? Auch so, dass es auf Fremdsprachwindows läuft. :gruebel: |
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; |
Re: Komme nicht weiter mit Zeitvergleichen?
Zitat:
|
Re: Komme nicht weiter mit Zeitvergleichen?
Zitat:
|
Re: Komme nicht weiter mit Zeitvergleichen?
Zitat:
|
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. |
Re: Komme nicht weiter mit Zeitvergleichen?
Zitat:
Und der Wert von Now wird sich deshalb gemerkt, damit auch das ausgegeben wird, was danach dann auch verglichen wird! |
Re: Komme nicht weiter mit Zeitvergleichen?
OK, weils keiner wirklich erklärt hat, versuch ich mich mal daran:
Wissenswerte Voraussetzungen:
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 |
Re: Komme nicht weiter mit Zeitvergleichen?
Ich verstehe jetzt die Logik nicht wie Delphi mit der Zeit umgeht.
Das hier funkt nicht:
Delphi-Quellcode:
aber das:
Label2.Caption:=TimeToStr(Now);
Label3.Caption:=TimeToStr(DateTimePicker2.Time); if Now=DateTimePicker2.Time then showmessage('ja');
Delphi-Quellcode:
obwohl das ja gleich ist. :roteyes:
Label2.Caption:=TimeToStr(Now);
Label3.Caption:=TimeToStr(DateTimePicker2.Time); if Label2.Caption=Label3.Caption then showmessage('ja'); |
Re: Komme nicht weiter mit Zeitvergleichen?
Zitat:
|
Re: Komme nicht weiter mit Zeitvergleichen?
Zitat:
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:
Habs nicht getestet, aber sollte so richtig sein.
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; |
Re: Komme nicht weiter mit Zeitvergleichen?
Zitat:
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:
Dann erscheint im Memo1 folgende Ausgabe:
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;
Code:
Die Interpretation überlasse ich Dir!
40105,5863273264
40105,5863273611 40105,5863273727 |
Re: Komme nicht weiter mit Zeitvergleichen?
Zitat:
|
Re: Komme nicht weiter mit Zeitvergleichen?
Delphi-Quellcode:
uses DateUtils;
|
Re: Komme nicht weiter mit Zeitvergleichen?
Hallo,
noch mal zu deinem Code.
Delphi-Quellcode:
In Zeile 3 ist Now schon wieder etwas weiter
Label2.Caption:=TimeToStr(Now);
Label3.Caption:=TimeToStr(DateTimePicker2.Time); if Now=DateTimePicker2.Time then showmessage('ja'); 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 |
Re: Komme nicht weiter mit Zeitvergleichen?
Zitat:
|
Re: Komme nicht weiter mit Zeitvergleichen?
Zitat:
StrToTime( '15:00' ) => 0.625 Now ist aber irgendwie immer > 1.0 (aktuell > 40105.0) |
Re: Komme nicht weiter mit Zeitvergleichen?
Wusste gar nicht, dass einfach zwei Zeiten zu vergleichen so kompliziert ist. :lol:
|
Re: Komme nicht weiter mit Zeitvergleichen?
Zitat:
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; |
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 |
Re: Komme nicht weiter mit Zeitvergleichen?
Zitat:
@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 :) |
Re: Komme nicht weiter mit Zeitvergleichen?
Zitat:
Und wieso vergleichst du mit >= und nicht einfach = ? :gruebel: |
Re: Komme nicht weiter mit Zeitvergleichen?
Zitat:
Es gibt mehrere Antworten, die sich genau darauf beziehen. |
Re: Komme nicht weiter mit Zeitvergleichen?
Nochmal: man vergleicht keine 2 Double-Werte mit =, da die Wahrscheinlichkeit gering ist, dass sie wirklich exakt übereinstimmen.
|
Re: Komme nicht weiter mit Zeitvergleichen?
Zitat:
|
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.
|
Re: Komme nicht weiter mit Zeitvergleichen?
Zitat:
|
Re: Komme nicht weiter mit Zeitvergleichen?
Zitat:
|
Re: Komme nicht weiter mit Zeitvergleichen?
Zitat:
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. |
Re: Komme nicht weiter mit Zeitvergleichen?
Zitat:
|
Re: Komme nicht weiter mit Zeitvergleichen?
Zitat:
|
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 09:25 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz