Link to home
Start Free TrialLog in
Avatar of blue220
blue220

asked on

Checking the difference between 2 formatted dates

This question builds from a previous question I ask/answered myself which had to do with a scheduling component but anyway the question is.

I have a form that has on it.

1 Timer (Timer1)
2 Labels (Label1 and Label2)

Every second Timer1 updates Label1 with the current date/time in this format  "4/22/04 @ 9:38:21 PM" minus the quotes ofcourse and on Label2 I have a static date/time in the same format as above but since it's not attached to the Timer it does not change (hence the word static)

Anyway how can I check to see if the time on Label2 is 5 minutes or more behind the time on Label1 (taking into account the @ symbol )

Thx,
Blue220
Avatar of shaneholmes
shaneholmes



procedure TForm1.Button1Click(Sender: TObject);
var
 P: Integer;
 T1: TDateTime;
 T2: TDateTime;
 AMins: Real;
begin
  P:= Pos('@',Label1.Caption) + 1;
  T1:= StrToDateTime(Copy(Label1.Caption,P, Length(Label1.Caption)));
  P:= Pos('@',Label2.Caption) + 1;
  T2:= StrToDateTime(Copy(Label2.Caption,P, Length(Label2.Caption)));
 AMins := (T2 - T1)*24*60;
 if AMins <= 5.00 then
  ShowMessage('It is 5 minutes or more behind!');
end;




Here it is again, with a comment for each line of code


procedure TForm1.Button1Click(Sender: TObject);
var
 P1: Integer;
 T1: TDateTime;
 P2: Integer;
 T2: TDateTime;
 AMins: Real;
begin
 //label1
 // get position of '@' character
 P1:= Pos('@',Label1.Caption) + 1;
 //extract the time portion after the '@' character
 T1:= StrToDateTime(Copy(Label1.Caption,P1, Length(Label1.Caption)));
 //label2
 // get position of '@' character
 P2:= Pos('@',Label2.Caption) + 1;
 //extract the time portion after the '@' character
 T2:= StrToDateTime(Copy(Label2.Caption,P2, Length(Label2.Caption)));
 //Get time difference in days * multiply against 24*60 for minutes
 AMins := (T2 - T1)*24*60;
 //display the difference in minutes
 ShowMessage(FormatFloat('0.00',AMins));
 if AMins <= 5.00 then
  ShowMessage('It is 5 minutes or more behind!');
end;

Shane
Avatar of blue220

ASKER

Thx for the reply but your solution does not take account the Date part of the caption so it would say it's 5 mins or more behind even if the date was set for 4/3/2050 which if I am not mistaken has not come up yet.
Try this. Some corrections to Shanes code

procedure TForm1.Button1Click(Sender: TObject);
var
 P: Integer;
 T1: TDateTime;
 T2: TDateTime;
 AMins: Real;
// ASecs: Real;
 str: string;
begin
  str := DateTimeToStr(Now);
  Label1.Caption := str;

  str := Label1.Caption;
  P:= Pos('@',str);
  if P > 0 then
    Delete(str,P,2);
  T1:= StrToDateTime(str);

  str := Label2.Caption;
  P:= Pos('@',str);
  if P > 0 then
    Delete(str,P,2);
  T2:= StrToDateTime(str);
 AMins := (T1 - T2)*24*60;
// ASecs := (T1 - T2)*24*60*60;
 if AMins >= 5.00 then                        
  ShowMessage('It is 5 minutes or more behind!');
// if ASecs >= 5.00 then
//  ShowMessage('It is 5 seconds or more behind!');
end;
In the VCL DateUtils.pas there is a nice function

function MinutesBetween(const ANow, AThen: TDateTime): Int64;

The DateFormat is a different problem: "4/22/04 @ 9:38:21 PM"

function FunnyStrToDate(aDateTime: string): TDateTime;

  function StripInt(var aText: string): Integer;
  var
    Pos: Integer;
  begin
    Result := -1;
    while (Length(aText) > 1) and not (aText[1] in ['0'..'9']) do
      Delete(aText, 1, 1);
    if Length(aText) > 0 then
    begin
      Pos := 1;
      while (Pos <= Length(aText)) and (aText[Pos] in ['0'..'9']) do
        Inc(Pos);
      Result := StrToInt(Copy(aText, 1, Pos - 1));
      Delete(aText, 1, Pos);
    end;
  end;

var
  Month, Day, Year, Hour, Minute, Second: Integer;
begin
  // Funny-format 4/22/04 @ 9:38:21 PM
  Month  := StripInt(aDateTime);
  Day    := StripInt(aDateTime);
  Year   := StripInt(aDateTime);
  Hour   := StripInt(aDateTime);
  Minute := StripInt(aDateTime);
  Second := StripInt(aDateTime);
  // correct year (1980 - 2079 supported)
  if Year < 80 then
    Inc(Year, 2000)
  else
    Inc(Year, 1900);
  // correct hour (AM/PM)
  aDateTime := Trim(aDateTime);
  if Length(aDateTime) > 1 then
    if UpperCase(aDateTime[1]) = 'P' then
      Hour := Hour + 12;
  // encode the date
  if (Year <> -1) and (Month <> -1) and (Day <> -1) and (Hour <> -1) and (Minute <> -1) and (Second <> -1) then
    Result := EncodeDate(Year, Month, Day) + EncodeTime(Hour, Minute, Second, 0)
  else
    raise Exception.Create('Illegal funny date format');
end;

The timer function could then read:

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Label1.Caption := UpperCase(FormatDateTime('m"/"d"/"yy @ h:nn:ss am/pm', Now));
  if (FunnyStrToDate(Label1.Caption) - FunnyStrToDate(Label2.Caption)) * MinsPerDay > 5 then
    Label3.Caption := 'More then 5 behind!'
  else
    Label3.Caption := '...';
end;

Regards Jacco

P.S You need DateUtils in the uses


Avatar of blue220

ASKER

Thanks guys for you help but still having problems. Couple things I should mention is I am no longer using a label to store the "Static" Date/Time values on but rather a StringGrid (one date/time value per row)

Here is the code I am using to add the values to the grid.

procedure TForm1.Button1Click(Sender: TObject);
Var
  RWC : integer;
begin
  RWC := GridView1.RowCount;
  Gridview1.AddRow(1);
  GridView1.Cells[0, RWC] := Edit1.Text;
  GridView1.Cells[1, RWC] := DateToStr(DateTimePicker1.Date)+ ' @ ' + TimeToStr(DateTimePicker2.Time);

As you can see the "Static" Date/Time Values come from 2 DateTimePickers with the @ symbol in between them.

Also it might be helpful to know the code I am using to add the current time to Label1 and also check to see if one of the values in the StringGrid matches the value on the Label1 so here is that code and prehaps it would be better to just build off  of it.

procedure TForm1.Timer1Timer(Sender: TObject);
Var
 I : Integer;
begin
 Label1.Caption := (DateToStr(Date)+ ' @ ' + TimeToStr(Time));
 For I := 0 to GridView1.RowCount - 1 do
  if GridView1.Cells[1,I] = Label1.Caption then
   ShowMessage('Match Found');
end;


I have upped the points for this question to 200 to make it worth your time.

Thx Again,
Blue220
What do You expect now?
This code checks for time in Label2 is 5 min "bigger" than time in grid row I.

procedure TForm1.Button1Click(Sender: TObject);
var
 P: Integer;
 T1: TDateTime;
 T2: TDateTime;
 AMins: Real;
 str: string;
begin
  str := Label1.Caption;
  P:= Pos('@',str);
  if P > 0 then
    Delete(str,P,2);
  T1:= StrToDateTime(str);

  str := GridView1.Cells[1,I];
  P:= Pos('@',str);
  if P > 0 then
    Delete(str,P,2);
  T2:= StrToDateTime(str);
 AMins := (T1 - T2)*24*60;
 if AMins >= 5.00 then                        
  ShowMessage(' GridView1 is 5 minutes or more behind Label1');
end;

Avatar of blue220

ASKER

Haven't tested the code but from what I can see it would only test for 1 cell in the Grid and I have many cells in the grid so that will not work.

Sorry you did not understand the code provided above but it was important to show you the changes I made to the program so we did not go round and round all day long with code that would not fit my needs....


Basically what I am doing is this...

Each time I press a Button the values I set in the DateTimePickers are added to one row on the Grid in the format "3/4/2004 @ 7:19:27 PM"  

Now on the timer I check every second ALL the rows in the Grid to see if one of those dates/times match the current date/time on the label and if so show the message "Match Found"

Now all I'm trying to do is the same thing as above with the checking and stuff but if it finds a date/time that is 5 mins or more behind the current date/time then show the message "5 mins or more behind current time" and it should be in the same for loop that I am using to check for a "matched" date/time.

With me so far... I hope so...


Anyway here again is the code I am using to check for a "matched" date/time.

procedure TForm1.Timer1Timer(Sender: TObject);
Var
   I : Integer;
begin
    Label1.Caption := (DateToStr(Date)+ ' @ ' + TimeToStr(Time));
    For I := 0 to GridView1.RowCount - 1 do
    if GridView1.Cells[1,I] = Label1.Caption then
       ShowMessage('Match Found');
end;

Like I said all that needs to be done is in the above For Loop add the code to check if one of the date/time values in the Grid is 5 mins or more behind the current date and time and if so then show the message "5 mins or more behind current time"

Hope that makes things clearer.
ASKER CERTIFIED SOLUTION
Avatar of mokule
mokule
Flag of Poland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of blue220

ASKER

Assuming your code takes into account the AM/PM part of the date/time it looks like it's working fine ... So thx for the help
thats messed up - uses my code and i don't even get an assist?

Ahhh - rite

Shane
Avatar of blue220

ASKER

Sorry bout that .... I forgot it started out with your code ... I will open a new question and award you points as well...