The main problem, apparently, is getting the last modified file time. I am using 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 a time file format. Then call UTCFileTimeToDateTime
to convert to TDateTime
, taking into account the prevailing local machine time zone. Then you can compare this value with Now
.
As for formatting, you already know how to do it. Your basic approach will work, and you just need to find out the details.
In the comments you say that
FormatDateTime('dd hh:nn:ss', 2.9);
shows a 1
for the day you expect a 2
. The problem is that this function formats dates, not time intervals. A value of 2.9
not considered elapsed time; rather, it is considered as an absolute date / time, 2.9
days after the Delphi era. I would use Trunc
and Frac
to get the number of days and part of the days respectively and work from there.
Days := Trunc(TimeDiff); Time := Frac(TimeDiff);
The following code, extracted directly from my code base, can give you a few 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;