Ian Branch 128 Posted September 23, 2020 Hi Team, Currently "FormatDateTime('dd:hh:mm:ss', EndDateTime - StartDateTime)" only allows 0-31 for the days. I am trying to subtract DateTimes that may be in the 100s to 200s of days apart and still want to represent the difference as just ddd:hh:mm:ss. i.e. 123:12:34:56 How can I do this please? Regards & TIA, Ian Share this post Link to post
limelect 48 Posted September 23, 2020 I do not know if it will help But Rxlib has has RxDateUtil.pas check it Share this post Link to post
Der schöne Günther 316 Posted September 23, 2020 You can easily use a TTimeSpan: program Project1; {$APPTYPE CONSOLE} uses System.SysUtils, System.DateUtils, System.TimeSpan; var StartDateTime, EndDateTime: TDateTime; TimePassed: TTimeSpan; begin StartDateTime := EncodeDateTime(2020, 01, 01, 00, 00, 00, 000); EndDateTime := Now(); TimePassed := TTimeSpan.FromDays(EndDateTime - StartDateTime); WriteLn(TimePassed.ToString()); ReadLn; end. which will output 266.07:29:15.1320000 If you want to have it differently, you can easily define your own format, like function formatTimespan(const timeSpan: TTimeSpan): String; begin Result := String.Format( '%d.%.2d:%.2d:%.2d', [ timeSpan.Days, timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds ]); end; which will then output 266.07:35:12 3 Share this post Link to post
Remy Lebeau 1436 Posted September 23, 2020 FormatDateTime() and other related functions are meant for formatting a specific date/time, not formatting a duration between 2 date/times. You are going to have to format a duration manually, like Der showed using TTimeSpan. Share this post Link to post
Ian Branch 128 Posted September 23, 2020 Hi Team, Thank you for your inputs. Appreciated. I have implemented the following.. FieldByName('Duration').AsString := (IntToStr(DaysBetween(FieldByName('FinishDateTime').AsDateTime, FieldByName('StartDateTime').AsDateTime)) + ':' + FormatDateTime('hh:mm:ss', FieldByName('FinishDateTime').AsDateTime - FieldByName('StartDateTime').AsDateTime)).PadLeft(12, '0'); This works exactly as I need. Regards, Ian Share this post Link to post
Ian Branch 128 Posted September 24, 2020 Lars, For some reason your post is not showing att. The code is used once only when the User logs out so time isn't really an issue but I take your point. If the code was used more often I would certainly optimise it as you suggest. The User's Administrator has the ability to generate ad-hoc reports, but is somewhat illiterate with SQL. By adding the Duration to the table he doesn't have to figure out how to create it. Regards, Ian Share this post Link to post
Fr0sT.Brutal 900 Posted September 24, 2020 Side note 1: for my projects I try to not rely on implementation details of data types. That is, assumption that Datetime1 - Datetime2 is "days between" Side note 2: usually it's more wise to store some meaningful value in DB and convert it to readable form on display (probably one day you'll want to calc some stats about durations - so you'll have to write 'ddd:hh:mm:ss' => Number convertor) Btw, here's function I use in my project: const NoneLbl = '(None)'; // Patterns RightNowLbl = 'less than a minute'; MinsPatt = '%d min'; HoursMinsPatt = '%d hr %.2d min'; DaysHoursMinsPatt = '%d d ' + HoursMinsPatt; // Formats number of minutes elapsed from AFrom to ATo. // If AFrom is 0 returns "None" (process wasn't started) function FormatMinutesSince(AFrom, ATo: TDateTime): string; var Mins: Integer; begin if AFrom = 0 then Exit(NoneLbl); Mins := Abs(MinutesSince(AFrom, ATo)); case Mins of 0: Result := RightNowLbl; 1..MinsPerHour-1: Result := Format(MinsPatt, [Mins]); MinsPerHour..MinsPerDay-1: Result := Format(HoursMinsPatt, [Mins div MinsPerHour, Mins mod MinsPerHour]) else Result := Format(DaysHoursMinsPatt, [Mins div MinsPerDay, (Mins mod MinsPerDay) div MinsPerHour, Mins mod MinsPerHour]); end; end; 1 Share this post Link to post
Lars Fosdal 1793 Posted September 24, 2020 @Ian Branch - I deleted the post. It was mostly off topic, which seems to be my default modus operandi Share this post Link to post
Remy Lebeau 1436 Posted September 24, 2020 (edited) 20 hours ago, Ian Branch said: This works exactly as I need. Actually, it doesn't, because as I said earlier, FormatDateTime() simply isn't intended to handle a duration between 2 date/time values like are you using it for. If you don't want to (or cannot) use TTimeSpan, then you should calculate the necessary components manually, eg: var // TS: TTimeSpan; StartDateTime, FinishDateTime: TDateTime; Days, Hours, Minutes, Seconds: Int64; begin StartDateTime := FieldByName('StartDateTime').AsDateTime; FinishDateTime := FieldByName('FinishDateTime').AsDateTime; { TS := TTimeSpan.Subtract(FinishDateTime, StartDateTime); FieldByName('Duration').AsString := Format('%.3d:%.2d:%.2d:%.2d', [TS.Days, TS.Hours, TS.Minutes, TS.Seconds]); } Seconds := SecondsBetween(FinishDateTime, StartDateTime); Days := Seconds div SecsPerDay; Seconds := Seconds mod SecsPerDay; Hours := Seconds div SecsPerHour; Seconds := Seconds mod SecsPerHour; Minutes := Seconds div SecsPerMin; Seconds := Seconds mod SecsPerMin; FieldByName('Duration').AsString := Format('%.3d:%.2d:%.2d:%.2d', [Days, Hours, Minutes, Seconds]); end; Edited September 24, 2020 by Remy Lebeau Share this post Link to post
Ian Branch 128 Posted September 24, 2020 Hi Remy, Intended or not, my equation produces exactly the same as yours. See attached screen shot. The columns are - Start, Finish Yours, Mine. I am quite willing to accept that my solution is more good luck than good management. 😉 Regards, Ian Share this post Link to post
Remy Lebeau 1436 Posted September 25, 2020 (edited) 20 hours ago, Ian Branch said: I am quite willing to accept that my solution is more good luck than good management. 😉 Which is exactly why you shouldn't rely on it. It depends on internal implementation details that could change one day in the future. Better to be explicit about the calculations so that if the implementation ever does change then the result will still work as expected. Edited September 25, 2020 by Remy Lebeau Share this post Link to post
Ian Branch 128 Posted September 26, 2020 Hi Remy, OK. You talked me into it. 😉 Regards & tks, Ian Share this post Link to post