View Issue Details

IDProjectCategoryView StatusLast Update
0035906FPCRTLpublic2019-08-03 08:11
ReporterOndrej PokornyAssigned ToSven Barth 
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
Platformwin32OSWindowsOS VersionWindows 10
Product Version3.3.1Product Build 
Target VersionFixed in Version3.3.1 
Summary0035906: TSearchRec.TimeStamp is not accurate on Windows
DescriptionTSearchRec.TimeStamp loses precision because it is calculated from the converted DOS file time and not the original Windows file time.
Steps To Reproduceprogram Project1;

uses Windows, SysUtils;

var
  xSR: TRawByteSearchRec;
  st, lt: TSystemTime;
begin
  if FindFirst('*', faAnyFile, xSR) = 0 then
  begin
    try
      repeat
        if not((xSR.Name='..') or (xSR.Name='.') or (xSR.Name='')) then
        begin
          Writeln(xSR.Name);
          Writeln(DateTimeToStr(FileDateToDateTime(xSR.Time)), ' - xSR.Time (inaccurate because of Longint precision)');
          Writeln(DateTimeToStr(xSR.TimeStamp), ' - xSR.TimeStamp (should be accurate - bug!): ');
          FileTimeToSystemTime(xSR.FindData.ftLastWriteTime, st);
          if SystemTimeToTzSpecificLocalTime(nil, st, lt) then
            Writeln(DateTimeToStr(SystemTimeToDateTime(lt)), ' - xSR.FindData.ftLastWriteTime (accurate)');
          Writeln;
        end;
      until FindNext(xSR) <> 0;
    finally
      FindClose(xSR);
    end;
  end;
  ReadLn;
end.
Additional InformationPatch attached.
TagsNo tags attached.
Fixed in Revision42559
FPCOldBugId
FPCTarget-
Attached Files
  • TSearchRec.GetTimeStamp-01.patch (1,274 bytes)
    Index: rtl/objpas/sysutils/filutil.inc
    ===================================================================
    --- rtl/objpas/sysutils/filutil.inc	(revision 42530)
    +++ rtl/objpas/sysutils/filutil.inc	(working copy)
    @@ -595,15 +595,39 @@
     { TUnicodeSearchRec }
     
     function TUnicodeSearchRec.GetTimeStamp: TDateTime;
    +{$if defined(win32) or defined(win64) or defined(wince)}
    +var
    +  st, lt: TSystemTime;
    +{$endif}
     begin
    +{$if defined(win32) or defined(win64) or defined(wince)}
    +  FileTimeToSystemTime(FindData.ftLastWriteTime, st);
    +  if SystemTimeToTzSpecificLocalTime(nil, st, lt) then
    +    Result := SystemTimeToDateTime(lt)
    +  else
    +    Result := SystemTimeToDateTime(st);
    +{$else}
       Result := FileDateToDateTime(Time);
    +{$endif}
     end;
     
     { TRawbyteSearchRec }
     
     function TRawbyteSearchRec.GetTimeStamp: TDateTime;
    +{$if defined(win32) or defined(win64) or defined(wince)}
    +var
    +  st, lt: TSystemTime;
    +{$endif}
     begin
    +{$if defined(win32) or defined(win64) or defined(wince)}
    +  FileTimeToSystemTime(FindData.ftLastWriteTime, st);
    +  if SystemTimeToTzSpecificLocalTime(nil, st, lt) then
    +    Result := SystemTimeToDateTime(lt)
    +  else
    +    Result := SystemTimeToDateTime(st);
    +{$else}
       Result := FileDateToDateTime(Time);
    +{$endif}
     end;
     
     { TUnicodeSymLinkRec }
    

Activities

Ondrej Pokorny

2019-07-30 00:00

reporter  

TSearchRec.GetTimeStamp-01.patch (1,274 bytes)
Index: rtl/objpas/sysutils/filutil.inc
===================================================================
--- rtl/objpas/sysutils/filutil.inc	(revision 42530)
+++ rtl/objpas/sysutils/filutil.inc	(working copy)
@@ -595,15 +595,39 @@
 { TUnicodeSearchRec }
 
 function TUnicodeSearchRec.GetTimeStamp: TDateTime;
+{$if defined(win32) or defined(win64) or defined(wince)}
+var
+  st, lt: TSystemTime;
+{$endif}
 begin
+{$if defined(win32) or defined(win64) or defined(wince)}
+  FileTimeToSystemTime(FindData.ftLastWriteTime, st);
+  if SystemTimeToTzSpecificLocalTime(nil, st, lt) then
+    Result := SystemTimeToDateTime(lt)
+  else
+    Result := SystemTimeToDateTime(st);
+{$else}
   Result := FileDateToDateTime(Time);
+{$endif}
 end;
 
 { TRawbyteSearchRec }
 
 function TRawbyteSearchRec.GetTimeStamp: TDateTime;
+{$if defined(win32) or defined(win64) or defined(wince)}
+var
+  st, lt: TSystemTime;
+{$endif}
 begin
+{$if defined(win32) or defined(win64) or defined(wince)}
+  FileTimeToSystemTime(FindData.ftLastWriteTime, st);
+  if SystemTimeToTzSpecificLocalTime(nil, st, lt) then
+    Result := SystemTimeToDateTime(lt)
+  else
+    Result := SystemTimeToDateTime(st);
+{$else}
   Result := FileDateToDateTime(Time);
+{$endif}
 end;
 
 { TUnicodeSymLinkRec }

Serge Anvarov

2019-07-31 10:35

reporter   ~0117518

1. FileTimeToSystemTime may also fail. I've come across this when time fields contain garbage.
2. Place the duplicate code in a separate function?

Sven Barth

2019-08-02 15:18

manager   ~0117545

I've done the implementation in a separate function, adjusted the SymLink ones as well and checked for the result of FileTimeToSystemTime (with fallback to the existing time).

Please test and close if okay.

Ondrej Pokorny

2019-08-03 08:11

reporter   ~0117550

Thank you very much!

Issue History

Date Modified Username Field Change
2019-07-30 00:00 Ondrej Pokorny New Issue
2019-07-30 00:00 Ondrej Pokorny File Added: TSearchRec.GetTimeStamp-01.patch
2019-07-31 10:35 Serge Anvarov Note Added: 0117518
2019-08-02 15:05 Sven Barth Assigned To => Sven Barth
2019-08-02 15:05 Sven Barth Status new => assigned
2019-08-02 15:18 Sven Barth Status assigned => resolved
2019-08-02 15:18 Sven Barth Resolution open => fixed
2019-08-02 15:18 Sven Barth Fixed in Version => 3.3.1
2019-08-02 15:18 Sven Barth Fixed in Revision => 42559
2019-08-02 15:18 Sven Barth FPCTarget => -
2019-08-02 15:18 Sven Barth Note Added: 0117545
2019-08-03 08:11 Ondrej Pokorny Status resolved => closed
2019-08-03 08:11 Ondrej Pokorny Note Added: 0117550