Page 2 of 2

Re: GetFileDate returns wrong time after DaylightSaving chan

Posted: Tue Aug 11, 2020 6:37 pm
by Pierre Bellisle
Hi Camille,

1601-01-01 01:00:00 is the oldest time that a FILETIME variable can use.
In fact it correspond to the time ZERO. Maximum is around year 30,827.
As MS say: Contains a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC).
When you got "1601-01-01", it is usually that the API GetFileTime could not get a valid time due to some error.
If I got a minute, I'll try to post some code that will tell the nature of the error...

Re: GetFileDate returns wrong time after DaylightSaving chan

Posted: Tue Aug 11, 2020 7:55 pm
by Pierre Bellisle
I edited my previous code to integrate verbose error checking plus a Boolean "FolderWanted" variable which let you choose between a file or folder.

Now, you should know the source of the error...

Re: GetFileDate returns wrong time after DaylightSaving chan

Posted: Tue Aug 11, 2020 8:52 pm
by camille
Thank you, Pierre!

Code: Select all

FolderWanted is FALSE
Daylight saving is on
Daylight saving offset is -60 minutes
File name is R:\TEMP\~DFC5E820D9B2E4F0C0.TMP
CreateFile error: Error 32 (0x20) : The process cannot access the file because it is being used by another process.
File system for R:\ is NTFS
Local last write file time is 1601-01-01 01:00:00
Unfortunately, lockhunter says that's not the case and the inbuilt GetFileDate() doesn't have a problem with that as well.

Code: Select all

zExeName = "R:\TEMP\~DFC5E820D9B2E4F0C0.TMP"
Debug FormatDate("%yyyy.%mm.%dd %hh:%ii:%ss", GetFileDate(zExeName, #PB_Date_Modified))
2020.08.11 12:48:02
Is there any other way to create a handle to the file without using CreateFile_() or is there any way to tell it that it shouldn't care about any locks?

Re: GetFileDate returns wrong time after DaylightSaving chan

Posted: Tue Aug 11, 2020 11:47 pm
by Pierre Bellisle
Camille,

Try this, in CreateFile_(), replace #GENERIC_READ with 0 (Zero). It will be more permissive...

Re: GetFileDate returns wrong time after DaylightSaving chan

Posted: Wed Aug 12, 2020 12:45 am
by Pierre Bellisle
Finally, to take another approach that may do better in your case.
Here is some code that use FindFirstFile_()
It is also shorter...

Code: Select all

;Read "File Times and Daylight Saving Time" at https://docs.microsoft.com/en-us/windows/win32/sysinfo/file-times
;_____________________________________________________________________________

Procedure.s WinError(ErrorCode.L) 
 Protected *BStr
 Protected *BStrData.String 
 Protected.s ErrorMessage
 Protected.l ErrorLen

 ErrorLen = FormatMessage_(#FORMAT_MESSAGE_FROM_SYSTEM | #FORMAT_MESSAGE_ALLOCATE_BUFFER, 
                           #Null$, ErrorCode, #Null$, @*BStr , #Null$, #Null$) 
 If ErrorLen 
   *BStrData.String = @*BStr
   ErrorMessage = *BStrData\s
   LocalFree_(*BStr)
   ProcedureReturn("Error " + Str(ErrorCode) + " (0x" + Hex(ErrorCode) + ") : " + Left(ErrorMessage, ErrorLen - 2))
 Else
   ProcedureReturn("Unknown error " + Str(ErrorCode) + " (0x" + Hex(ErrorCode) + ")")
 EndIf

EndProcedure
;_____________________________________________________________________________

Procedure.s FileTimeToInternationalTime(File_Time) 
 Protected Sys_Time.SystemTime

 FileTimeToSystemTime_(File_Time, @Sys_Time)
 ProcedureReturn(Str(Sys_Time\wyear)                 + "-" + RSet(Str(Sys_Time\wMonth), 2, "0") + "-" + 
                 RSet(Str(Sys_Time\wDay) ,   2, "0") + " " + RSet(Str(Sys_Time\wHour),  2, "0") + ":" + 
                 RSet(Str(Sys_Time\wMinute), 2, "0") + ":" + RSet(Str(Sys_Time\wSecond), 2, "0")) 
 
EndProcedure
;______________________________________________________________________________

 Define zExeName.s{#MAX_PATH}
 Define zFileSystem.s{20}
 Define zDrive.s{4}
 Define.s sBuffer
 Define.i hFile 
 Define.l LastError
 Define.FILETIME LastWriteTime
 Define.FILETIME FileTimeLocal
 Define.SYSTEMTIME SystemTimeLocal
 Define.TIME_ZONE_INFORMATION TimeZoneInfo
 Define.WIN32_FIND_DATA FileData ;File data structure    

 If GetTimeZoneInformation_(TimeZoneInfo) = #TIME_ZONE_ID_DAYLIGHT 
     sBuffer = sBuffer + "Daylight saving is on"
 Else ;#TIME_ZONE_ID_STANDARD
     sBuffer = sBuffer + "Daylight saving is off"
 EndIf
 sBuffer = sBuffer + #CRLF$ + #CRLF$ + "Daylight saving offset is " + Str(TimeZoneInfo\DaylightBias) + " minutes"  + #CRLF$ + #CRLF$
 
 zExeName = ProgramFilename() 

 ;If you want to get the parent folder else REM those two lines
 zExeName = GetPathPart(zExeName) ;To get folder only
 zExeName = Left(zExeName, Len(zExeName) -1) ;Remove last backslash
 
 zDrive   = Left(zExeName, 3)

 GetVolumeInformation_(zDrive, 0, 0, 0, 0, 0, @zFileSystem, SizeOf(zFileSystem))
 sBuffer = sBuffer + "File system for " + Left(zExeName, 3) + " is " + zFileSystem + #CRLF$ + #CRLF$ 

 sBuffer = sBuffer + "File name is " + zExeName + #CRLF$ + #CRLF$

 hFile = FindFirstFile_(zExeName, @FileData) ;Get files or folders 
 If hFile <> #INVALID_HANDLE_VALUE ;Make sure we have a valid handle
   LastWriteTime = FileData\ftLastWriteTime ; \ftCreationTime \ftLastAccessTime \ftLastWriteTime
   FindClose_(hFile) 
 Else
   LastError = GetLastError_()
   sBuffer = sBuffer + "FindFirstFile_ error: " + WinError(LastError) + #CRLF$ + #CRLF$ ;Show it in readable text
 EndIf

 FileTimeToSystemTime_(LastWriteTime, @SystemTimeLocal)                     ;Convert to local time part A
 SystemTimeToTzSpecificLocalTime_(#Null, SystemTimeLocal, @SystemTimeLocal) ;Convert to local time part B
 SystemTimeToFileTime_(SystemTimeLocal, @FileTimeLocal)                     ;Convert to local time part C

 sBuffer = sBuffer + "Local last write file time is " + FileTimeToInternationalTime(FileTimeLocal) 

 MessageBox_(#HWND_DESKTOP, sBuffer + #CRLF$, "File time", #MB_OK | #MB_TOPMOST)

;______________________________________________________________________________
;

Re: GetFileDate returns wrong time after DaylightSaving chan

Posted: Wed Aug 12, 2020 11:35 am
by camille
Many thanks, Pierre! :D

Both of your versions work flawlessly!

I've run it over a bunch of folders and files (both with locked ones as well) with 100% success rate.

Re: GetFileDate returns wrong time after DaylightSaving chan

Posted: Wed Aug 12, 2020 4:25 pm
by Pierre Bellisle
Great! :-)

Re: GetFileDate returns wrong time after DaylightSaving change

Posted: Fri May 20, 2022 7:17 pm
by highend
May I ask:

If you already have:

Code: Select all

 FileTimeToSystemTime_(LastWriteTime, @SystemTimeLocal)                     ;Convert to local time part A
 SystemTimeToTzSpecificLocalTime_(#Null, SystemTimeLocal, @SystemTimeLocal) ;Convert to local time part B
 SystemTimeToFileTime_(SystemTimeLocal, @FileTimeLocal)                     ;Convert to local time part C
Why is it necessary to convert it "again" via the

Code: Select all

FileTimeToInternationalTime(File_Time)
procedure?

Re: GetFileDate returns wrong time after DaylightSaving change

Posted: Mon Jun 13, 2022 3:39 pm
by Pierre Bellisle
highend wrote: Fri May 20, 2022 7:17 pm Why is it necessary to convert it "again" via the FileTimeToInternationalTime(File_Time) procedure?
A little late since last May, still...

In fact, it is not necessary, for me the point was to convert a FileTime variable to another FileTime variable.Wich is done via FileTimeToSystemTime(), SystemTimeToTzSpecificLocalTime() and SystemTimeToFileTime().

FileTimeToInternationalTime() is meant solely as a common function to show a FileTime result in a human readable way and is not really part of the main logic conversion.

One may use only FileTimeToSystemTime() and SystemTimeToTzSpecificLocalTime() if the result need to be in SystemTime format.