4

現在からファイルの最終変更日時までの経過時間 (適切にフォーマットされた) を計算する必要があります。このようなもの、私の場合のみ、違いは数日、数か月、さらには数年になる可能性があります。

私はこれを試しました:

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;

しかし、(1) うまくいかず、(2) フォーマットを改善したい。

最終的に私の目標は、次のようなものを持つことです。

  • 時差 < 1 日 ==> これを表示: 12:00:01
  • 時差 >= 1 日 ==> これを表示: 25 日、12:00:01
  • Time Diff >= 1 year ==> 表示: 2 年、3 か月、10 日、12:00:01

どうすればそれができるか知っている人はいますか?

ありがとう!

4

1 に答える 1

10

主な問題は、ファイルの最終変更時刻を把握することです。次のコードを使用します。

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;

を呼び出しLastWriteTimeて、最終変更時刻をファイル時刻形式で取得します。次に、マシンの一般的なローカル タイム ゾーンを考慮しUTCFileTimeToDateTimeて変換するように呼び出します。TDateTimeその後、その値を と比較できますNow

フォーマットに関しては、あなたはすでにそれを行う方法を知っているようです。基本的なアプローチは機能し、詳細を具体化するだけで済みます。


コメントであなたはそれを言う

FormatDateTime('dd hh:nn:ss', 2.9);

1を期待する日には を表示します2。問題は、この関数が時間間隔ではなく日付をフォーマットすることです。この値2.9は経過時間として扱われるのではなく2.9、Delphi エポックから数日後の絶対日付/時刻として扱われます。と を使用TruncFracて、それぞれ日数と日数の一部を取得し、そこから作業します。

Days := Trunc(TimeDiff);
Time := Frac(TimeDiff);

私のコードベースから直接抽出された次のコードは、いくつかの指針を与えるかもしれません。その入力は秒単位ですが、正しいパスに設定する必要があることに注意してください。

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;
于 2012-05-12T14:59:10.347 に答える