Recent

Author Topic: FileAge: milliseconds is always 000 [SOLVED by rvk]  (Read 15743 times)

totya

  • Hero Member
  • *****
  • Posts: 722
FileAge: milliseconds is always 000 [SOLVED by rvk]
« on: October 08, 2016, 12:29:44 pm »
Hi!

With the FileAge function, the milliseconds (zzz) always 000, why? Win7 x64.

Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormCreate(Sender: TObject);
  2. begin
  3.   Memo1.Clear;
  4.  
  5.   Memo1.Lines.Add(DateTimeToStr(FileDateToDateTime(FileAge('project1.exe'))));
  6.  
  7.   Memo1.Lines.Add(FormatDateTime('nn:ss:zzz', FileDateToDateTime(FileAge('project1.exe'))));
  8. end;

Thanks!

Lazarus 1.6 official.
« Last Edit: October 15, 2016, 09:15:05 pm by totya »

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12641
  • FPC developer.
Re: FileAge: milliseconds is always 000
« Reply #1 on: October 08, 2016, 12:35:53 pm »
Try to use the variant with the OUT parameter:

http://www.freepascal.org/docs-html/rtl/sysutils/fileage.html and not go over filedatetodatetime.

ASerge

  • Hero Member
  • *****
  • Posts: 2475
Re: FileAge: milliseconds is always 000
« Reply #2 on: October 08, 2016, 12:39:12 pm »
Hi!
With the FileAge function, the milliseconds (zzz) always 000, why? Win7 x64.
FileAge don't contain milliseconds
Details on https://msdn.microsoft.com/en-us/library/windows/desktop/ms724274%28v=vs.85%29.aspx

totya

  • Hero Member
  • *****
  • Posts: 722
Re: FileAge: milliseconds is always 000
« Reply #3 on: October 08, 2016, 12:52:01 pm »
Hi!
With the FileAge function, the milliseconds (zzz) always 000, why? Win7 x64.
FileAge don't contain milliseconds
Details on https://msdn.microsoft.com/en-us/library/windows/desktop/ms724274%28v=vs.85%29.aspx

Hi!

MS-DOS? Why?

Quote
A file time is a 64-bit value that represents the number of 100-nanosecond intervals

Source:

https://msdn.microsoft.com/en-us/library/windows/desktop/ms724290(v=vs.85).aspx

totya

  • Hero Member
  • *****
  • Posts: 722
Re: FileAge: milliseconds is always 000
« Reply #4 on: October 08, 2016, 01:01:35 pm »
Try to use the variant with the OUT parameter:

http://www.freepascal.org/docs-html/rtl/sysutils/fileage.html and not go over filedatetodatetime.

Hi!

I tried it, but nothing changed:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormCreate(Sender: TObject);
  2. var
  3.   FileDateTime: TDateTime;
  4. begin
  5.   Memo1.Clear;
  6.  
  7.   Memo1.Lines.Add(DateTimeToStr(FileDateToDateTime(FileAge('project1.exe'))));
  8.  
  9.   Memo1.Lines.Add(FormatDateTime('nn:ss:zzz', FileDateToDateTime(FileAge('project1.exe'))));
  10.  
  11.   FileAge('project1.exe', FileDateTime);
  12.   Memo1.Lines.Add(FormatDateTime('nn:ss:zzz', FileDateTime));
  13. end;

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: FileAge: milliseconds is always 000
« Reply #5 on: October 08, 2016, 03:03:52 pm »
I tried it, but nothing changed:
Why should there be a a change ?

totya

  • Hero Member
  • *****
  • Posts: 722
Re: FileAge: milliseconds is always 000
« Reply #6 on: October 08, 2016, 04:16:38 pm »
I tried it, but nothing changed:
Why should there be a a change ?

May I ask, do you see the subject of this topic? :)

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: FileAge: milliseconds is always 000
« Reply #7 on: October 08, 2016, 04:26:51 pm »
May I ask, do you see the subject of this topic? :)
Of course you may  :)

May i ask in return if you understand how a file-system stores these values ?

The most important part of information is missing from your question in that the answer depends on the underlying file-system.

Look at the filetime structure explained by microsoft and how this structure is filled depending on the underlying file-system.

Quote
Not all file systems can record creation and last access time and not all file systems record them in the same manner. For example, on NT FAT, create time has a resolution of 10 milliseconds, write time has a resolution of 2 seconds, and access time has a resolution of 1 day (really, the access date). On NTFS, access time has a resolution of 1 hour. Therefore, the GetFileTime function may not return the same file time information set using the SetFileTime function. Furthermore, FAT records times on disk in local time. However, NTFS records times on disk in UTC. For more information, see File Times.

totya

  • Hero Member
  • *****
  • Posts: 722
Re: FileAge: milliseconds is always 000
« Reply #8 on: October 08, 2016, 04:53:43 pm »
The file system is NTFS, this is the default fiesystem on Windows XP and above.

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: FileAge: milliseconds is always 000
« Reply #9 on: October 08, 2016, 05:00:06 pm »
In addition to that, ASerge was on the right track but poorly chosen the wrong implementation e.g. dos vs windows.

Windows version reads:
Code: [Select]
Function FileAge (Const FileName : UnicodeString): Longint;
var
  Handle: THandle;
  FindData: TWin32FindDataW;
begin
  Handle := FindFirstFileW(Pwidechar(FileName), FindData);
  if Handle <> INVALID_HANDLE_VALUE then
    begin
      Windows.FindClose(Handle);
      if (FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
        If WinToDosTime(FindData.ftLastWriteTime,Result) then
          exit;
    end;
  Result := -1;
end;

Code: [Select]
Function WinToDosTime (Const Wtime : TWinFileTime;var DTime:longint):longbool;
var
  lft : TWinFileTime;
begin
  WinToDosTime:=FileTimeToLocalFileTime(WTime,lft) and
                FileTimeToDosDateTime(lft,longrec(dtime).hi,longrec(dtime).lo);
end;

Code: [Select]
function FileTimeToLocalFileTime(const ft : TWinFileTime;var lft : TWinFileTime) : longbool;
  stdcall; external 'kernel32' name 'FileTimeToLocalFileTime';

function FileTimeToDosDateTime(const ft :TWinFileTime;var data,time : word) : longbool;
  stdcall; external 'kernel32' name 'FileTimeToDosDateTime';

Which tells us:
1) FileTimeToLocalFileTime
2) FileTimeToDosDateTime

And... behold the infamous FILETIME structure is there again, as explained in my previous post.

Now, go blame your filesystem  :D

rvk

  • Hero Member
  • *****
  • Posts: 6940
Re: FileAge: milliseconds is always 000
« Reply #10 on: October 08, 2016, 05:08:53 pm »
It's not the filesystem that's at fault. The problem is the FileDateToDateTime() function in FPC. It is not accurate enough to translate milliseconds. If you use the FileTimeToDateTime() in jcl you'll get your milliseconds.

Code: Pascal  [Select][+][-]
  1. uses Windows;
  2.  
  3. const
  4.   FileTimeBase      = -109205.0;
  5.   FileTimeStep: Extended = 24.0 * 60.0 * 60.0 * 1000.0 * 1000.0 * 10.0; // 100 nSek per Day
  6.  
  7. function FileTimeToDateTime(const FileTime: TFileTime): TDateTime;
  8. begin
  9.   Result := Int64(FileTime) / FileTimeStep;
  10.   Result := Result + FileTimeBase;
  11. end;
  12.  
  13. procedure TForm1.FormCreate(Sender: TObject);
  14. var
  15.   F: TSearchRec;
  16.   Local: TFileTime;
  17. begin
  18.   memo1.clear;
  19.   FindFirst('project1.exe', faAnyFile and not faDirectory, F);
  20.   try
  21.     FileTimeToLocalFileTime(F.FindData.ftCreationTime, Local);
  22.     memo1.lines.add('Created: ' + FormatDateTime('dd.mm.yyyy hh:nn:ss.zzz', FileTimeToDateTime(Local)));
  23.     FileTimeToLocalFileTime(F.FindData.ftLastAccessTime, Local);
  24.     memo1.lines.add('Last access: ' + FormatDateTime('dd.mm.yyyy hh:nn:ss.zzz', FileTimeToDateTime(Local)));
  25.     FileTimeToLocalFileTime(F.FindData.ftLastWriteTime, Local);
  26.     memo1.lines.add('Last write: ' + FormatDateTime('dd.mm.yyyy hh:nn:ss.zzz', FileTimeToDateTime(Local)));
  27.   finally
  28.     SysUtils.FindClose(F);
  29.   end;
  30. end;
(You'll need to adjust for your local-time but there are function for that too, i.e. FileTimeToLocalFileTime)

My result (for project1.exe in %temp%, hence the old creation date)
Code: [Select]
Created: 01.10.2016 18:39:04.443
Last access: 01.10.2016 18:39:04.443
Last write: 08.10.2016 17:09:38.869

Saving the project elsewhere and doing it again you'll get:
Code: [Select]
Created: 08.10.2016 17:12:24.227
Last access: 08.10.2016 17:12:24.227
Last write: 08.10.2016 17:12:26.016

So yeah, this is really due to an inaccuracy in FPC.
« Last Edit: October 08, 2016, 05:13:54 pm by rvk »

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: FileAge: milliseconds is always 000
« Reply #11 on: October 08, 2016, 05:22:41 pm »
Thank you for the correction rvk (though, the file-system has its influence).

Quote
So yeah, this is really due to an inaccuracy in FPC.
Delphi compatibility or worth a bug-report ?

The annoying part there is that fpc documentation on filedatetodatetime advertsies itself to be used with FileAge.
« Last Edit: October 08, 2016, 05:24:56 pm by molly »

rvk

  • Hero Member
  • *****
  • Posts: 6940
Re: FileAge: milliseconds is always 000
« Reply #12 on: October 08, 2016, 05:26:28 pm »
Quote
So yeah, this is really due to an inaccuracy in FPC.
Delphi compatibility or worth a bug-report ?
Not sure if the FileDateToDateTime() in Delphi is more accurate (can't test that right now). If it is then it should be fixed in FPC. Otherwise it can stay the way it is, with maybe a wiki-entry to explain you can use another function (i.e. FileTimeToDateTime from jcl) for milliseconds.

totya

  • Hero Member
  • *****
  • Posts: 722
Re: FileAge: milliseconds is always 000
« Reply #13 on: October 08, 2016, 05:51:29 pm »
HI!

Thanks rvk master, for your answer!

Otherwise, it seems to me, FileAge is inaccurate, for example, with FileAge function I got this: 17:38:44
With your code I got:  17:38:43.106
With TotalCommander I got: 17:38:43

This is one second difference. (Molly will ask: What difference? Why? Go blame your Windows OS, the Linux is the best) ;)

Thanks again!

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: FileAge: milliseconds is always 000
« Reply #14 on: October 08, 2016, 06:00:40 pm »
Otherwise, it seems to me, FileAge is inaccurate, for example, with FileAge function I got this: 17:38:44
Rounded up... hmz, that's even stranger. Did you use FileDateToDateTime for that or another function ?

afai was able to see FileDateToDateTime simply truncates.

Quote
This is one second difference. (Molly will ask: What difference? Why? Go blame your Windows OS, the Linux is the best) ;)
Just for good measures: I never blamed the OS, rather the file-system. There is a major difference there. A file-system can be used on any OS that supports it (these days anyhows)

Somewhat related thread here on ML.

 

TinyPortal © 2005-2018