4

I have two TDateTime variables, like this:

s := StrToDateTime('03/03/2017 10:10:12');
e := StrToDateTime('04/04/2017 10:10:12');

I need to find out the difference between them, in hh:mm:ss format.

The ...Between() functions are not helping me here.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Tina Soltanian
  • 81
  • 1
  • 2
  • 8
  • What Delphi version? Some have the capability to do this available; others don't and require you to write something yourself. – Ken White Apr 04 '17 at 22:29
  • How exactly not helping? What did you try so far? – Free Consulting Apr 05 '17 at 05:08
  • the delphi version is 10 seattle, i tried subtract itself, then timespan but none of them return the total difference which somehow is correct because the result could be maybe 45 hours and 20 minutes and 25 seconds which is not a correct format for hour even if i get total difference is minute or second is good i can take care of the rest – Tina Soltanian Apr 05 '17 at 20:03

3 Answers3

9

Use the DateUtils.SecondsBetween function:

Uses
  DateUtils,SysUtils;

function TimeDiffStr(const s1,s2: String): String;
var
  t1,t2: TDateTime;
  secs: Int64;
begin
  t1 := StrToDateTime(s1); 
  t2 := StrToDateTime(s2); 
  secs := SecondsBetween(t1,t2);
  Result := Format('%2.2d:%2.2d:%2.2d',[secs div SecsPerHour,(secs div SecsPerMin) mod SecPerMin,secs mod SecsPerMin]);
end;

begin
  WriteLn(TimeDiffStr('03/03/2017 10:10:12','04/04/2017 10:10:12'));
  ReadLn;
end.

From the number of seconds, calculate the hours,minutes and remaining seconds.


If you want the difference in minutes, use the DateUtils.MinutesBetween function:

function TimeDiffStr(const s1,s2: String): String;
var
  t1,t2: TDateTime;
  minutes: Int64;
begin
  t1 := StrToDateTime(s1); 
  t2 := StrToDateTime(s2); 
  minutes := MinutesBetween(t1,t2);
  Result := Format('%2.2d:%2.2d:%2.2d',[minutes div MinsPerHour,minutes mod MinsPerHour,0]);
end;
LU RD
  • 34,438
  • 5
  • 88
  • 296
  • 1
    You should use the constants in the `SysUtils` unit instead of using "magic numbers" directly in code, eg: `Result := Format('%2.2d:%2.2d:%2.2d',[secs div SecsPerHour, (secs div SecsPerMin) mod SecsPerMin, secs mod SecsPerMin]);` and `Result := Format('%2.2d:%2.2d:%2.2d', [minutes div MinsPerHour, minutes mod MinsPerHour, 0]);` ` – Remy Lebeau Apr 04 '17 at 23:10
  • @RemyLebeau, yes that makes sense, corrected. Thanks. – LU RD Apr 04 '17 at 23:17
  • this one works too but why in the help it says this function returns only the difference of the seconds i have no idea – Tina Soltanian Apr 05 '17 at 20:15
  • oh no i think i really lost in the code and help, i think i got it wrong, because i was looking for something so difficult and impossible – Tina Soltanian Apr 05 '17 at 20:16
  • 1
    @TinaSoltanian: you are misreading what the documentation is actually saying. `SecondsBetween()` returns the total difference between the two date/time values, expressed in whole seconds. – Remy Lebeau Apr 05 '17 at 20:19
8

You can use TTimeSpan (from the System.TimeSpan unit).

program Project1;

{$APPTYPE CONSOLE}

uses
  System.SysUtils, System.TimeSpan;

var
  StartDate, EndDate: TDateTime;
  TS: TTimeSpan;
  Temp: string;
begin
  StartDate := StrToDateTime('03/03/2017 10:10:12');
  EndDate := StrToDateTime('04/04/2017 10:10:12');
  TS := TTimeSpan.Subtract(EndDate, StartDate);
  Temp := TS;
  WriteLn(Temp);  // Outputs 32.00:00:00
  // The next line outputs the same as the one above
  WriteLn(Format('%.2d:%.2d:%.2d:%.2d', [TS.Days, TS.Hours, TS.Minutes, TS.Seconds]));
  WriteLn(TS.TotalMinutes); // Outputs 4.60800000000000E+0004
  WriteLn(Trunc(TS.TotalMinutes)); // Outputs 46080

  // This one will give the output you want (768:00:00)
  WriteLn(Format('%.2d:%.2d:%.2d', [TS.Days * 24 + TS.Hours, TS.Minutes, TS.Seconds]));
  ReadLn;
end.
Ken White
  • 123,280
  • 14
  • 225
  • 444
  • 1
    Shouldn't you swap the `StartDate` and `EndDate` parameters? `TS := TTimeSpan.Subtract(EndDate, StartDate);` That is equivalent to `EndDate - StartDate`. – Remy Lebeau Apr 04 '17 at 23:11
  • @Remy: Caught that. On the phone right now; will edit in a few. – Ken White Apr 04 '17 at 23:34
  • 2
    @Remy: Updated. (My mother hates it when I put her on speaker.) – Ken White Apr 04 '17 at 23:45
  • 1
    this is awesome, thank you so much, i really have no idea why all the things that i tested was not working, when Im tired im kind of getting lost in codes. any way thanks :) – Tina Soltanian Apr 05 '17 at 20:12
4

First off, don't use hard-coded strings for date/time values. That is subject to localization issues, and it is just wasted overhead anyway. Use the SysUtils.EncodeDate() and SysUtils.EncodeTime() functions, or the DateUtils.EncodeDateTime() function.

Second, the ...Between() functions can indeed be usedneed, in particular SecondsBetween(). You can calculate the individual components from that return value.

Try something like this:

uses
  ..., SysUtils, DateUtils;

var
  s, e: TDateTime;
  diff: Int64;
  days, hours, mins, secs: Integer;
  s: string;
begin
  s := EncodeDateTime(2017, 3, 3, 10, 10, 12, 0);
  e := EncodeDateTime(2017, 4, 4, 10, 10, 12, 0);

  diff := SecondsBetween(e, s);

  days := diff div SecsPerDay;
  diff := diff mod SecsPerDay;

  hours := diff div SecsPerHour;
  diff := diff mod SecsPerHour;

  mins := diff div SecsPerMin;
  diff := diff mod SecsPerMin;

  secs := diff;

  s := Format('%d:%d:%d:%d', [days, hours, mins, secs]);
end;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • but as far as i read the seconds between just return the difference of seconds not the total difference – Tina Soltanian Apr 05 '17 at 20:04
  • @TinaSoltanian: That is not true. `SecondsBetween()` returns the total number of whole seconds between the two date/time values. That takes minutes/hours/days/years into account. Same goes for the other `...Between()` functions. – Remy Lebeau Apr 05 '17 at 20:14
  • yeahhh thank you so muchhhh, you all helped me a lot. now i can complete my code – Tina Soltanian Apr 05 '17 at 20:19