GetDateFileModified for Daylight Savings Time

2019-05-31 16:36发布

问题:

function DateTimeToFileTime(FileTime: TDateTime): TFileTime;
var
  LocalFileTime, Ft: TFileTime;
  SystemTime: TSystemTime;
begin
  Result.dwLowDateTime := 0;
  Result.dwHighDateTime := 0;
  DateTimeToSystemTime(FileTime, SystemTime);
  SystemTimeToFileTime(SystemTime, LocalFileTime);
  LocalFileTimeToFileTime(LocalFileTime, Ft);
  Result := Ft;
end;

function ExtractShortDate(ATimeIn: TDateTime): string;
// Convert DateTime to short date string
begin
  Result := FormatDateTime('mm/dd/yyyy', ATimeIn);
end;

function ExtractTime(ATimeIn: TDateTime): string;
// Convert DateTime to am/pm time string
begin
  Result := FormatDateTime('hh:mm AM/PM', ATimeIn);
end;

function GetDateFileModified(AFileName: string): string;
// Return the file modified date as a string in local time
var
  SR: TSearchRec;
  UTCTime: Windows.TFileTime;
  GMTST: Windows.TSystemTime;
  LocalST: Windows.TSystemTime;
  ModifyDT: TDateTime;
  TZ: Windows._TIME_ZONE_INFORMATION;
begin
  Result := '';
  if FindFirst(AFileName, faAnyFile, SR) = 0 then
  begin
    UTCTime := SR.FindData.ftLastWriteTime;
    if FileTimeToSystemTime(UTCTime, GMTST) then
    begin
       // Get Timezone Information
      if GetTimeZoneInformation(TZ) <> 0 then
        if SystemTimeToTzSpecificLocalTime(@TZ, GMTST, LocalST) then
        begin
          ModifyDT := SystemTimeToDateTime(LocalST);
          Result := ExtractShortDate(ModifyDT) + ' ' + ExtractTime(ModifyDT);
        end
        else
        begin
          TaskMessageDlg('Unable To Convert Time', 'Unable to convert SystemTime To LocalTime',
            mtInformation, [mbOk], 0);
          Result := '';
          exit;
        end;
    end
    else
    begin
      TaskMessageDlg('Unable To Convert Time', 'Unable to convert FileTime To SystemTime',
        mtInformation, [mbOk], 0);
      Result := '';
      exit;
    end;
  end
  else
    TaskMessageDlg('File Not Found', ExtractFileName(AFileName) + ' does not exist.',
      mtInformation, [mbOk], 0);
  FindClose(SR);
end;

The original code posted did not return the correct time. The original code was replaced with working code so that others may find this beneficial.

Update: The code provides the correct time now thanks to all that assisted.

回答1:

The problem is highlighted in the MSDN docs for FileTimeToLocalFileTime:

FileTimeToLocalFileTime uses the current settings for the time zone and daylight saving time. Therefore, if it is daylight saving time, this function will take daylight saving time into account, even if the time you are converting is in standard time. You can use the following sequence of functions as an alternative.

FileTimeToSystemTime / SystemTimeToTzSpecificLocalTime / SystemTimeToFileTime

You need to use the three functions specified whenever you look at a file after a daylight savings change that was created before the change (but this method of course also works when you and the file creation are both on the same side of the daylight savings change).