I need to calculate the elapsed time (nicely formatted) between now and a file's last modification date/time, ie. something like this, only in my case, the difference can be in days, months or even years.
I tried this:
var
TimeDiff : Double;
begin
TimeDiff := Now - FileAgeEx('C:\my-file.txt');
if (TimeDiff >= 1) then
Caption := FormatDateTime('dd hh:nn:ss', TimeDiff)
else
Caption := FormatDateTime('hh:nn:ss', TimeDiff);
end;
But (1) it doesn't work and (2) I'd like a better formatting.
Ultimately my goal is to have something like this:
Anyone knows how can I do that?
Thanks!
The main problem would appear to be getting hold of the last modified time of the file. I use the following code:
function LastWriteTime(const FileName: string): TFileTime;
var
AttributeData: TWin32FileAttributeData;
begin
if not GetFileAttributesEx(PChar(FileName), GetFileExInfoStandard, @AttributeData) then
RaiseLastOSError;
Result := AttributeData.ftLastWriteTime;
end;
function UTCFileTimeToSystemTime(const FileTime: TFileTime): TSystemTime;
//returns equivalent time in current locality, taking account of daylight saving
var
LocalFileTime: Windows.TFileTime;
begin
Windows.FileTimeToLocalFileTime(FileTime, LocalFileTime);
Windows.FileTimeToSystemTime(LocalFileTime, Result);
end;
function UTCFileTimeToDateTime(const FileTime: TFileTime): TDateTime;
begin
Result := SystemTimeToDateTime(UTCFileTimeToSystemTime(FileTime));
end;
You call LastWriteTime
to get the last modified time in file time format. Then call UTCFileTimeToDateTime
to convert into TDateTime
accounting for the prevailing local time zone of the machine. You can then compare that value with Now
.
As regards the formatting, you already appear to know how to do that. You basic approach will work and you just need to flesh out the details.
In the comments you say that
FormatDateTime('dd hh:nn:ss', 2.9);
shows a 1
for the day when you would expect a 2
. The problem is that this function formats dates rather than time intervals. The value 2.9
is not treated as an elapsed time, rather it is treated as an absolute date/time, 2.9
days after the Delphi epoch. I would use Trunc
and Frac
to obtain number of days, and the part of days respectively, and work from there.
Days := Trunc(TimeDiff);
Time := Frac(TimeDiff);
The following code, extracted directly from my codebase, may give you some pointers. Note that its input is in seconds, but it should set you on the right path.
function CorrectPlural(const s: string; Count: Integer): string;
begin
Result := IntToStr(Count) + ' ' + s;
if Count<>1 then begin
Result := Result + 's';
end;
end;
function HumanReadableTime(Time: Double): string;
//Time is in seconds
const
SecondsPerMinute = 60;
SecondsPerHour = 60*SecondsPerMinute;
SecondsPerDay = 24*SecondsPerHour;
SecondsPerWeek = 7*SecondsPerDay;
SecondsPerYear = 365*SecondsPerDay;
var
Years, Weeks, Days, Hours, Minutes, Seconds: Int64;
begin
Try
Years := Trunc(Time/SecondsPerYear);
Time := Time - Years*SecondsPerYear;
Weeks := Trunc(Time/SecondsPerWeek);
Time := Time - Weeks*SecondsPerWeek;
Days := Trunc(Time/SecondsPerDay);
Time := Time - Days*SecondsPerDay;
Hours := Trunc(Time/SecondsPerHour);
Time := Time - Hours*SecondsPerHour;
Minutes := Trunc(Time/SecondsPerMinute);
Time := Time - Minutes*SecondsPerMinute;
Seconds := Trunc(Time);
if Years>5000 then begin
Result := IntToStr(Round(Years/1000))+' millennia';
end else if Years>500 then begin
Result := IntToStr(Round(Years/100))+' centuries';
end else if Years>0 then begin
Result := CorrectPlural('year', Years) + ' ' + CorrectPlural('week', Weeks);
end else if Weeks>0 then begin
Result := CorrectPlural('week', Weeks) + ' ' + CorrectPlural('day', Days);
end else if Days>0 then begin
Result := CorrectPlural('day', Days) + ' ' + CorrectPlural('hour', Hours);
end else if Hours>0 then begin
Result := CorrectPlural('hour', Hours) + ' ' + CorrectPlural('minute', Minutes);
end else if Minutes>0 then begin
Result := CorrectPlural('minute', Minutes);
end else begin
Result := CorrectPlural('second', Seconds);
end;
Except
Result := 'an eternity';
End;
end;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With