GetFileDate returns wrong time after DaylightSaving change
- Pierre Bellisle
- User
- Posts: 35
- Joined: Wed Jun 27, 2018 5:12 am
Re: GetFileDate returns wrong time after DaylightSaving chan
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...
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...
- Pierre Bellisle
- User
- Posts: 35
- Joined: Wed Jun 27, 2018 5:12 am
Re: GetFileDate returns wrong time after DaylightSaving chan
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...
Now, you should know the source of the error...
Re: GetFileDate returns wrong time after DaylightSaving chan
Thank you, Pierre!
Unfortunately, lockhunter says that's not the case and the inbuilt GetFileDate() doesn't have a problem with that as well.
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?
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
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
- Pierre Bellisle
- User
- Posts: 35
- Joined: Wed Jun 27, 2018 5:12 am
Re: GetFileDate returns wrong time after DaylightSaving chan
Camille,
Try this, in CreateFile_(), replace #GENERIC_READ with 0 (Zero). It will be more permissive...
Try this, in CreateFile_(), replace #GENERIC_READ with 0 (Zero). It will be more permissive...
Last edited by Pierre Bellisle on Mon Sep 21, 2020 3:49 am, edited 1 time in total.
- Pierre Bellisle
- User
- Posts: 35
- Joined: Wed Jun 27, 2018 5:12 am
Re: GetFileDate returns wrong time after DaylightSaving chan
Finally, to take another approach that may do better in your case.
Here is some code that use FindFirstFile_()
It is also shorter...
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
Many thanks, Pierre!
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.
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.
- Pierre Bellisle
- User
- Posts: 35
- Joined: Wed Jun 27, 2018 5:12 am
Re: GetFileDate returns wrong time after DaylightSaving change
May I ask:
If you already have:
Why is it necessary to convert it "again" via the
procedure?
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
Code: Select all
FileTimeToInternationalTime(File_Time)
- Pierre Bellisle
- User
- Posts: 35
- Joined: Wed Jun 27, 2018 5:12 am
Re: GetFileDate returns wrong time after DaylightSaving change
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.