It is currently Wed Jan 27, 2021 8:21 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 22 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: GetFileDate returns wrong time after DaylightSaving change
PostPosted: Mon Oct 28, 2013 11:00 pm 
Offline
Enthusiast
Enthusiast

Joined: Thu Apr 02, 2009 9:48 pm
Posts: 115
Hi!

Yesterday I came accross a strange bug (at least I think it's a bug as I can't see any logic in the current behaviour).

When I use 'GetFileDate' to read the '#PB_Date_Modified' Date of a file I get different results depending on the DaylightSaving status.

For example the 5.20 x86 purebasic.exe:
GetFileDate returns >1379419754< >2013.09.17 12:09:14< when run with a systemdate BEFORE the daylight-saving change on 27.10.2013 (at least here in Austria), and when I change the systemdate to the current date (after the daylight saving change) I get a different result: >1379416154< >2013.09.17 11:09:14<

Personally I think 'GetFileDate' should always return the same value - regardless of the current daylight saving state.
When I check the modified date directly in windows explorer I'll get always the same result, independent of the current system date (always with 12:09).

So I've wrote a small workaround procedure 'GetFileDateTZ':
(based on the 'Remarks' here: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724277%28v=vs.85%29.aspx)
Code:
EnableExplicit

Procedure.i GetFileDateTZ(Filename.s, Datetype.i, UseUTC.b=#False)
   Protected FileHdl.i
   Protected Create.FILETIME
   Protected Access.FILETIME
   Protected Write.FILETIME
   Protected SystemTime.SYSTEMTIME
   Protected LocalTime.SYSTEMTIME
   
   FileHdl = ReadFile(#PB_Any, Filename)
   If FileHdl
      If Not GetFileTime_(FileID(FileHdl), @Create, @Access, @Write)
         Debug "GetFileDateTZ - GetFileTime Error!!"
         ProcedureReturn 0
      EndIf
      
      CloseFile(FileHdl)
      
      Select Datetype
         Case #PB_Date_Created
            If Not FileTimeToSystemTime_(@Create, @SystemTime)
               Debug "GetFileDateTZ - FileTimeToSystemTime Error!!"
            EndIf
            
         Case #PB_Date_Accessed
            If Not FileTimeToSystemTime_(@Access, @SystemTime)
               Debug "GetFileDateTZ - FileTimeToSystemTime Error!!"
            EndIf
            
         Case #PB_Date_Modified
            If Not FileTimeToSystemTime_(@Write, @SystemTime)
               Debug "GetFileDateTZ - FileTimeToSystemTime Error!!"
            EndIf
            
         Default
            Debug "GetFileDateTZ - Invalid Datetype >"+Str(Datetype)+"<"
            ProcedureReturn 0
      EndSelect
      
      If UseUTC
         LocalTime=SystemTime
      Else
         If Not SystemTimeToTzSpecificLocalTime_(#Null, @SystemTime, @LocalTime)
            Debug "GetFileDateTZ - SystemTimeToTzSpecificLocalTime Error!!"
            ProcedureReturn 0
         EndIf
      EndIf
      
      ProcedureReturn Date(LocalTime\wYear, LocalTime\wMonth, LocalTime\wDay, LocalTime\wHour, LocalTime\wMinute, LocalTime\wSecond)

   Else
      Debug "GetFileDateTZ - ReadFile Error!!"
      ProcedureReturn 0
   EndIf

EndProcedure

Define FileTime.i
Define sFile.s=#PB_Compiler_Home+"\purebasic.exe"


FileTime=GetFileDate(sFile, #PB_Date_Modified)
Debug "GetFileDate:         >"+Str(FileTime)+"< >"+FormatDate("%yyyy.%mm.%dd %hh:%ii:%ss", FileTime)+"<"

FileTime=GetFileDateTZ(sFile, #PB_Date_Modified)
Debug "GetFileDateTZ:       >"+Str(FileTime)+"< >"+FormatDate("%yyyy.%mm.%dd %hh:%ii:%ss", FileTime)+"<"

FileTime=GetFileDateTZ(sFile, #PB_Date_Modified, #True)
Debug "GetFileDateTZ: (UTC) >"+Str(FileTime)+"< >"+FormatDate("%yyyy.%mm.%dd %hh:%ii:%ss", FileTime)+"<"


When searching the forum for known problems with 'GetFileDate' I found this one: http://www.purebasic.fr/english/viewtopic.php?t=50902 and so I've included also a parameter to my 'GetFileDateTZ' procedure that allows to get the date as UTC - this way it not even changes in case the local timezone is changed.

Until it's fixed I'll use my workaround :)

Edit: Changed the procedure slightly, removed the check for filesize, this almost doubled the speed (it's still slower than the original GetFileDate - but fast enough for all my purposes)


Last edited by nalor on Mon Oct 28, 2013 11:30 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: GetFileDate returns wrong time after DaylightSaving chan
PostPosted: Mon Oct 28, 2013 11:26 pm 
Offline
Addict
Addict

Joined: Thu Jun 07, 2007 3:25 pm
Posts: 3967
Location: Berlin, Germany
This is a known problem, caused by the NTFS file system: Files created in summer (when daylight saving time is in effect) show a wrong time stamp in winter (when daylight saving time is not in effect), and vice versa. When using FAT32, then you'll not encounter this problem.
I did not check the details what PB exactly does in this context, but it probably just retrieves the time stamp from the file system.

_________________
Please excuse my flawed English. My native language is PureBasic.
Search
RSBasic's backups


Top
 Profile  
Reply with quote  
 Post subject: Re: GetFileDate returns wrong time after DaylightSaving chan
PostPosted: Mon Oct 28, 2013 11:37 pm 
Offline
Enthusiast
Enthusiast

Joined: Thu Apr 02, 2009 9:48 pm
Posts: 115
Hi LittleJohn!

I tried what you've suggested and copied the purebasic.exe to a FAT32 volume and now I'll get always a constant date: 2013.09.17 11:09:14

but my windows explorer still tells me it has been changed at 12:09 ;)

So to be honest I came to the conclusion that I cannot trust the return value of GetFileDate... it's neither the time I see in my explorer nor the UTC time - so I don't know what time it should be...


Top
 Profile  
Reply with quote  
 Post subject: Re: GetFileDate returns wrong time after DaylightSaving chan
PostPosted: Tue Oct 29, 2013 12:00 am 
Offline
Addict
Addict

Joined: Thu Jun 07, 2007 3:25 pm
Posts: 3967
Location: Berlin, Germany
Hi nalor,

unfortunately I currently don't have the time to go into details. E.g. this article provides some background information which might be of interest for you.

_________________
Please excuse my flawed English. My native language is PureBasic.
Search
RSBasic's backups


Top
 Profile  
Reply with quote  
 Post subject: Re: GetFileDate returns wrong time after DaylightSaving chan
PostPosted: Tue Oct 29, 2013 1:34 pm 
Offline
Addict
Addict
User avatar

Joined: Tue May 10, 2005 10:00 pm
Posts: 1652
Location: Norway
I use this code:

Code:
  protected time.FILETIME, locTime.FILETIME, sysTime.SYSTEMTIME

  id = readFile(0, path)
 
  select when
    case 0 ;created   
      getFileTime_(id, time, 0, 0)
    case 1 ;accessed
      getFileTime_(Id, 0, time, 0)
    case 2 ;modified/written
      getFileTime_(id, 0, 0, time)           
  endSelect
  ;correct for daylight savings in effect
  fileTimeToLocalFileTime_(time, locTime)
  fileTimeToSystemTime_(locTime, sysTime)

  closeFile(0)


Top
 Profile  
Reply with quote  
 Post subject: Re: GetFileDate returns wrong time after DaylightSaving chan
PostPosted: Tue Oct 29, 2013 6:49 pm 
Offline
Enthusiast
Enthusiast

Joined: Thu Apr 02, 2009 9:48 pm
Posts: 115
Hi again!

@utopiomania:
I've tried your code - but I think it does the same as the internal 'GetFileDate' function because this is my result:
[18:40:37] GetFileDate: >1379416154< >2013.09.17 11:09:14<
[18:40:37] GetFileDateTZ: >1379419754< >2013.09.17 12:09:14<
[18:40:37] GetFileDateTZ: (UTC) >1379412554< >2013.09.17 10:09:14<
[18:40:37] GetFileDateTZ2: >1379416154< >2013.09.17 11:09:14<

Your version is the one labelled 'GetFileDateTZ2' - it shows exactly the same (wrong) time as the internal function.

The link that posted LittleJohn gives the explanation for this incorrect behaviour:

Quote:
To convert a file time to local time, use the FileTimeToLocalFileTime function. However, FileTimeToLocalFileTime uses the current settings for the time zone and daylight saving time. Therefore, if it is daylight saving time, it takes daylight saving time into account, even if the file time you are converting is in standard time.


So using 'FileTimeToLocalTime' is never reliable when used in conjunction with daylight saving...


Top
 Profile  
Reply with quote  
 Post subject: Re: GetFileDate returns wrong time after DaylightSaving chan
PostPosted: Wed Oct 30, 2013 10:45 am 
Offline
Administrator
Administrator

Joined: Fri May 17, 2002 4:39 pm
Posts: 14181
Location: France
As it seems to be a Windows glitch, I moved this topic out of the bug forum


Top
 Profile  
Reply with quote  
 Post subject: Re: GetFileDate returns wrong time after DaylightSaving chan
PostPosted: Wed Oct 30, 2013 5:01 pm 
Offline
Addict
Addict
User avatar

Joined: Tue May 10, 2005 10:00 pm
Posts: 1652
Location: Norway
nalor, the code I posted from copies files from cameras, and renames them according to their write date/time stamp onto pc's with or without daylight savings in effect, and does it correctly.
Without the conversions below the filenames was one hour wrong half of the year, but maybe that is a different problem than yours. :)

Code:
;correct for daylight savings in effect
  fileTimeToLocalFileTime_(time, locTime)
  fileTimeToSystemTime_(locTime, sysTime)


Top
 Profile  
Reply with quote  
 Post subject: Re: GetFileDate returns wrong time after DaylightSaving chan
PostPosted: Wed Oct 30, 2013 7:51 pm 
Offline
Enthusiast
Enthusiast

Joined: Thu Apr 02, 2009 9:48 pm
Posts: 115
To be honest - I have a solution that works for me and so I can live with it - but I'd still expect that 'GetFileDate' returns the same timestamp as I can see directly in the explorer in windows.
Everything else is wrong in my eyes.

@Fred : And so I still think it's a bug in your GetFileDate implementation and not a glitch in windows because Microsoft clearly defines how it should be done correct (in the remarks section: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724277%28v=vs.85%29.aspx ).
And my small workaround procedure does it as microsoft says and I get the correct value.

@utopiomania : nothing against your code, if it works for you it's fine, but when use it I get wrong results.
My Windows Explorer tells me the purebasic.exe of 5.20 has been changed on >2013.09.17 12:09:14<, so this is the result I'd expect, but the only reliable way is as I got it from the MS page (GetFileDateTZ):

Summertime on my system (2013.10.01 systemdate)
NTFS volume:
[19:44:08] GetFileDate: >1379419754< >2013.09.17 12:09:14<
[19:44:08] GetFileDateTZ: >1379419754< >2013.09.17 12:09:14<
[19:44:08] GetFileDateTZ2: >1379419754< >2013.09.17 12:09:14<

FAT32 volume:
[19:43:29] GetFileDate: >1379419754< >2013.09.17 12:09:14<
[19:43:29] GetFileDateTZ: >1379419754< >2013.09.17 12:09:14<
[19:43:29] GetFileDateTZ2: >1379419754< >2013.09.17 12:09:14<


Wintertime on my system (2013.10.30 systemdate):
NTFS volume:
[19:44:56] GetFileDate: >1379416154< >2013.09.17 11:09:14<
[19:44:56] GetFileDateTZ: >1379419754< >2013.09.17 12:09:14<
[19:44:56] GetFileDateTZ2: >1379416154< >2013.09.17 11:09:14<

FAT32 volume:
[19:37:38] GetFileDate: >1379419754< >2013.09.17 12:09:14<
[19:37:38] GetFileDateTZ: >1379419754< >2013.09.17 12:09:14<
[19:37:38] GetFileDateTZ2: >1379416154< >2013.09.17 11:09:14<

As last time 'GetFileDateTZ2' is your implementation, as you can see during wintertime it's still 1 hour off...

Finally I can say: GetFileDate returns wrong results during wintertime on NTFS volumes.


Last edited by nalor on Sun Aug 09, 2020 7:07 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: GetFileDate returns wrong time after DaylightSaving chan
PostPosted: Sat Aug 08, 2020 9:19 pm 
Offline
User
User

Joined: Tue Nov 19, 2019 12:52 pm
Posts: 61
Does anyone know how to change the code from the first post so that it works for folders instead of files?


Top
 Profile  
Reply with quote  
 Post subject: Re: GetFileDate returns wrong time after DaylightSaving chan
PostPosted: Sun Aug 09, 2020 7:10 pm 
Offline
Enthusiast
Enthusiast

Joined: Thu Apr 02, 2009 9:48 pm
Posts: 115
camille wrote:
Does anyone know how to change the code from the first post so that it works for folders instead of files?


I haven't tried - but I think it should with folders out of the box - simply because the windows api command 'getfiledate' is also designed to work with folders:

https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfiletime

Does it return something wrong for you? Can you post an example what is wrong?


Top
 Profile  
Reply with quote  
 Post subject: Re: GetFileDate returns wrong time after DaylightSaving chan
PostPosted: Sun Aug 09, 2020 8:42 pm 
Offline
User
User

Joined: Tue Nov 19, 2019 12:52 pm
Posts: 61
Code:
Define sFile.s="D:\Temp\1.txt"


Output:
Code:
GetFileDate:         >1460658816< >2016.04.14 18:33:36<
GetFileDateTZ:       >1460658816< >2016.04.14 18:33:36<
GetFileDateTZ: (UTC) >1460651616< >2016.04.14 16:33:36<


Now with the belonging folder:
Code:
Define sFile.s="D:\Temp"


Output:
Code:
GetFileDate:         >1592905274< >2020.06.23 09:41:14<
GetFileDateTZ - ReadFile Error!!
GetFileDateTZ:       >0< >1970.01.01 00:00:00<
GetFileDateTZ - ReadFile Error!!
GetFileDateTZ: (UTC) >0< >1970.01.01 00:00:00<


I've found a way that works with both files and folders but this way has its own problems.
GetFileDate() is more reliable (though not 100%) on files in the %TEMP% folder and only reports 0 for some files / folders
while the api way reports 0 for more (maybe 10%) files / folders...

If you want to try it, replace this:
Code:
   FileHdl = ReadFile(#PB_Any, Filename)
   If FileHdl
      If Not GetFileTime_(FileID(FileHdl), @Create, @Access, @Write)
         ProcedureReturn 0
      EndIf

      CloseFile(FileHdl)


with this:
Code:
      FileHdl = CreateFile_(path,
                            #GENERIC_READ|#GENERIC_WRITE,
                            #FILE_SHARE_READ|#FILE_SHARE_DELETE,
                            0,
                            #OPEN_EXISTING,
                            #FILE_FLAG_BACKUP_SEMANTICS,
                            0)
      If FileHdl
        If Not GetFileTime_(FileHdl, @Create, @Access, @Write)
          ProcedureReturn 0
        EndIf

        CloseHandle_(FileHdl)


Top
 Profile  
Reply with quote  
 Post subject: Re: GetFileDate returns wrong time after DaylightSaving chan
PostPosted: Tue Aug 11, 2020 6:11 am 
Offline
User
User
User avatar

Joined: Wed Jun 27, 2018 5:12 am
Posts: 21
On my side I do not see any Windows glitch. Either on NTFS or FAT.
Use the Microsoft recommend way. See File Times - File Times and Daylight Saving Time

FileTimeToSystemTime, SystemTimeToTzSpecificLocalTime and SystemTimeToFileTime

Code:
;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 SelfExeName() ;GetExeNameGetFileNameFullFilename
 Protected zExeName.s{#MAX_PATH}

 GetModuleFileName_(GetModuleHandle_(0), @zExeName, #MAX_PATH) ;Get exe full name
 ProcedureReturn(zExeName) ;

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.l FolderWanted
 Define.FILETIME LastWriteTime
 Define.FILETIME FileTimeLocal
 Define.SYSTEMTIME SystemTimeLocal
 Define.TIME_ZONE_INFORMATION TimeZoneInfo
 
 FolderWanted = 001
 If FolderWanted
   sBuffer = "FolderWanted is TRUE" + #CRLF$ + #CRLF$
 Else
    sBuffer = "FolderWanted is FALSE" + #CRLF$ + #CRLF$
 EndIf

 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$
 
 GetModuleFileName_(GetModuleHandle_(0), @zExeName, #MAX_PATH) ;Get exe full name ;Also Result$ = ProgramFilename()
 If FolderWanted
   zExeName = GetPathPart(zExeName) ;To get folder time
 EndIf
 ;;For test... zExeName = zExeName + ".Error"
 sBuffer = sBuffer + #CRLF$ + "File name is " + zExeName + #CRLF$ + #CRLF$

 If FolderWanted
   hFile = CreateFile_(zExeName, #FILE_LIST_DIRECTORY, #FILE_SHARE_READ, 0, #OPEN_EXISTING, #FILE_FLAG_BACKUP_SEMANTICS, 0)   
 Else
   hFile = CreateFile_(zExeName, #GENERIC_READ, #FILE_SHARE_READ, 0, #OPEN_EXISTING, #FILE_ATTRIBUTE_NORMAL, 0)
 EndIf

 If hFile = #INVALID_HANDLE_VALUE ;An error occured
   LastError = GetLastError_() ;Get error id
   sBuffer   = sBuffer + "CreateFile error: " + WinError(LastError) + #CRLF$ + #CRLF$ ;Shot it in readable text
 Else ;Handle is good
   If GetFileTime_(hFile, 0, 0, @LastWriteTime) = 0 ;Some error occured
     LastError = GetLastError_() ;Get error id
     ;;LastError = 5 ;Test error id
     sBuffer = sBuffer + "GetFileTime error: " + WinError(LastError) + #CRLF$ + #CRLF$ ;Shot it in readable text
   EndIf
   CloseHandle_(hFile)
 EndIf

 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$

 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 + #CRLF$ + "Local last write file time is " + FileTimeToInternationalTime(FileTimeLocal)

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


Last edited by Pierre Bellisle on Tue Aug 11, 2020 7:51 pm, edited 2 times in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: GetFileDate returns wrong time after DaylightSaving chan
PostPosted: Tue Aug 11, 2020 6:38 am 
Offline
User
User
User avatar

Joined: Wed Jun 27, 2018 5:12 am
Posts: 21
Note to use the code on a folder instead of a filename.

As example, REM out
;GetModuleFileName_(GetModuleHandle_(0), @zExeName, #MAX_PATH) ;Get exe full name
and add just after...
zExeName = "C:\Windows" ;Use what you want...

REM out
;hFile = CreateFile_(zExeName, #GENERIC_READ, #FILE_SHARE_READ, 0, #OPEN_EXISTING, #FILE_ATTRIBUTE_NORMAL, 0)
And add just after...
hFile = CreateFile_(zExeName, #FILE_LIST_DIRECTORY, #FILE_SHARE_READ, 0, #OPEN_EXISTING, #FILE_FLAG_BACKUP_SEMANTICS, 0)


Top
 Profile  
Reply with quote  
 Post subject: Re: GetFileDate returns wrong time after DaylightSaving chan
PostPosted: Tue Aug 11, 2020 9:02 am 
Offline
User
User

Joined: Tue Nov 19, 2019 12:52 pm
Posts: 61
Hi Pierre,

Code:
Daylight saving is on
Daylight saving offset is -60 minutes
File name is R:\TEMP\~DF4393CAED6853E7CB.TMP
File system for R:\ is NTFS
Local last write file time is 1601-01-01 01:00:00


Code:
Daylight saving is on
Daylight saving offset is -60 minutes
File name is R:\TEMP\~DFE9BD699FAE1B9233.TMP
File system for R:\ is NTFS
Local last write file time is 2020-08-11 09:33:02


So at least on my side there are glitches...
Btw, the real last write time for the first file is: 2020-08-11 09:40:31

My guess is that there is some lock on the first file but "LockHunter" (https://lockhunter.com/) doesn't report one.
Don't know why the code shows 1601-01-01 01:00:00 for that file. Windows Explorer and all other file manager show the correct date + time.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 22 posts ]  Go to page 1, 2  Next

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye