在将文件日期转换为TDateTime或从TDateTime转换文件日期时,如何修复不一致问题

时间:2009-09-19 10:38:35

标签: delphi datetime delphi-2009

我在我的3层应用中本地缓存文件。要检查是从本地缓存还是从服务器读取文件,我比较文件日期。我发现在将文件日期转换为TDateTime时会出现这种情况,反之则存在不一致和值很少匹配的值。这是一些解释问题的代码

procedure TestFileDateConversion;
const
  Dir = 'c:\TestDir\';
  Filename = 'test.txt';
var
  FileDate, NewFileDate: TDateTime;
  FilePath: String;
  FileHandle: THandle;
begin
  ForceDirectories(Dir);

  FilePath := concat(Dir, Filename);

  // Create the file if it doesn't already exist
  FileCreate(FilePath);

  FileDate := now;

  // Set the file date
  try
    FileHandle := FileOpen(FileName, fmOpenWrite OR fmShareDenyNone);

    if FileHandle > 0 Then
      FileSetDate(FileHandle, DateTimeToFileDate(FileDate));
  finally
    FileClose(FileHandle);
  end;

  // Check that the expected file date and the actual file date match
  if (FileAge(FilePath, NewFileDate)) and (FileDate <> NewFileDate) then
    ShowMessage('File dates do not match'); // More often than not, they don't
end;

我确定这是由一些舍入问题引起的。有人知道解决方法吗?

3 个答案:

答案 0 :(得分:4)

你对四舍五入是正确的。 TDateTime实际上是一个浮点数,并且所有浮点数都有舍入问题。特别是比较平等是一个问题。 CompareDateTime之类的功能可以提供帮助。还有一些文件系统没有像TDateTime那样的精度。某些文件系统只有2秒的精度。因此,您可能需要使用SecondsBetween函数来决定使用较低的精度进行比较。

答案 1 :(得分:1)

使用Math单元中的'SameValue'函数比较TDateTime。如果两个值彼此非常接近,则执行“模糊”比较,返回相等性(如果您愿意,可以在默认增量内修改)。你的规则应该是:永远不要执行

If FloatA = FloatB then
   ....

可以这样做:

If FloatA = 0.0 then
  ....

但就是这样。

布赖恩。

答案 2 :(得分:0)

使用系统日期时间更新文件不是一个好主意,如果你有不同时区的电脑需要骑它。使用哈希函数来知道文件何时不同并且需要更新。

散列文件很简单,例如,请查看http://delphi.about.com/od/objectpascalide/a/delphi-md5-hash.htm

无论如何,getFileTime的分辨率低于tdatetime(在旧系统中更大),但只有几秒钟,那么你需要在比较中进行一轮。

来自MSDN“并非所有文件系统都能记录创建和上次访问时间,并非所有文件系统都以相同的方式记录它们。例如,在FAT上,创建时间的分辨率为10毫秒,写入时间的分辨率为2秒,访问时间的分辨率为1天(实际上是访问日期)。因此,GetFileTime函数可能不会返回使用SetFileTime设置的相同文件时间信息.NTFS延迟更新文件的上次访问时间到最后一次访问后一小时。“