on one file that i know for sure is same date on both drives (as seen in
explorer)
i get the following times
Time for file 1: 3005030930305536
Time for file 2: 3005030913683296
lngCompare <1>
as you can see the filetimes are different, but in explorer they are the
same
what am i doing wrong?
in my compareSaveTime sub
'get file times(function below)
retFileTimeA = GetFileSavedTimeObj(msFullName)
retFileTimeB = GetFileSavedTimeObj(sFileNameB)
If msFullName = "Z:\0\Support\MCS\LISP\StartUp\MCS.MNL" Then
LogEntry "Time for file 1: " & CStr(retFileTimeA.dwHighDateTime) &
CStr(retFileTimeA.dwLowDateTime)
LogEntry "Time for file 2: " & CStr(retFileTimeB.dwHighDateTime) &
CStr(retFileTimeB.dwLowDateTime)
End If
Dim lngCompare As Integer
'using api function to comparetimes
'Private Declare Function CompareFileTime Lib "kernel32" (lpFileTime1 As
FILETIME, lpFileTime2 As FILETIME) As Long
lngCompare = CompareFileTime(retFileTimeA, retFileTimeB)
'just put this in for debug...this is the one with wrong report...probably
all are...
If msFullName = "Z:\0\Support\MCS\LISP\StartUp\MCS.MNL" Then
LogEntry "lngCompare ", lngCompare
End If
'the getFileTime function
Private Function GetFileSavedTimeObj(ByVal sFileName As String) As FILETIME
Dim lngFhndl As Long
Dim ftCreated As FILETIME
Dim ftLastAccess As FILETIME
Dim ftSaved As FILETIME
'local time
Dim ftlocSaved As FILETIME
'system time
Dim ftsysSaved As SYSTEMTIME
lngFhndl = FileHandle(sFileName)
'fill in filetime structures
'If the function succeeds, the return value is nonzero.
'If the function fails, the return value is zero.
Dim lrtn As Long
lrtn = GetFileTime(lngFhndl, ftCreated, ftLastAccess, ftSaved)
CloseFile (lngFhndl)
If lrtn = 0 Then
' Debug.Print "GetFileTime Failed on " & sFileName
Else
'Convert the file time to the local file time
FileTimeToLocalFileTime ftSaved, ftlocSaved
GetFileSavedTimeObj = ftlocSaved
End If
End Function
any hints appreciated
mark
If the files are on different file systems (NTFS vs FAT, e.g.) then
you can't make a guaranteed comparison of file times. The usual rule
is that if file times are within two seconds, they're the same
(because FAT file systems only store the time to the closest even
number of seconds).
You could add logic to detect the file system and enforce exactness
when they're the same, and allow a 2-second window otherwise.
--
Jim Mack
Twisted tees at http://www.cafepress.com/2050inc
"We sew confusion"
"Jim Mack" <jm...@mdxi.nospam.com> wrote in message
news:ed9MugVi...@TK2MSFTNGP05.phx.gbl...
> mp wrote:
>> I seem to be getting a result i'm not expecting
>> using api to get file time of two 'identical' files on different
>> drives working on a file backup app to synchronize my portable hard
>> drive and laptop
snip
>
> If the files are on different file systems (NTFS vs FAT, e.g.) then
> you can't make a guaranteed comparison of file times. The usual rule
> is that if file times are within two seconds, they're the same
> (because FAT file systems only store the time to the closest even
> number of seconds).
>
> You could add logic to detect the file system and enforce exactness
> when they're the same, and allow a 2-second window otherwise.
>
> --
> Jim Mack
> Twisted tees at http://www.cafepress.com/2050inc
> "We sew confusion"
Thanks much! hit the nail on the head...
to expose my ignorance (not hard) how would i add 2 seconds to the api call
lngCompare = CompareFileTime(retFileTimeA, retFileTimeB) just returns an
integer
i'm guessing i can interpret FileTimeA.dwHighDateTime or
FileTimeA.dwLowDateTime
in some way to compute seconds?
mark
take a look at FileTimeToSystemTime
http://msdn.microsoft.com/en-us/library/ms724280(VS.85).aspx
and perhaps FileTimeToLocalFileTime
http://msdn.microsoft.com/en-us/library/ms724277(VS.85).aspx
Thanks for the links,
the closest thing i can find around there is
dwRet = StringCchPrintf(lpszString, dwSize,
TEXT("%02d/%02d/%d %02d:%02d"),
stLocal.wMonth, stLocal.wDay, stLocal.wYear,
stLocal.wHour, stLocal.wMinute);
i can probably convert that to vb, but will have to check if there is a
Seconds member on that struct...
will search that shortly when i get time ... no pun intended ... :-)
Thanks
mark
Yeah, you've got to ignore the VB.Net examples they've started adding
everywhere.
> i can probably convert that to vb, but will have to check if there is a
> Seconds member on that struct...
"Type", and there is
> will search that shortly when i get time ... no pun intended ... :-)
something like this should get you started
Private Type SYSTEMTIME
wYear As Integer
wMonth As Integer
wDayOfWeek As Integer
wDay As Integer
wHour As Integer
wMinute As Integer
wSecond As Integer
wMilliseconds As Integer
End Type
Private Type FILETIME
dwLowDateTime As Long
dwHighDateTime As Long
End Type
Private Declare Function SystemTimeToFileTime Lib "kernel32" _
(ByRef lpSystemTime As SYSTEMTIME, ByRef lpFileTime As FILETIME) As Long
Private Declare Function FileTimeToSystemTime Lib "kernel32" _
(ByRef lpFileTime As FILETIME, ByRef lpSystemTime As SYSTEMTIME) As Long
Private Declare Function FileTimeToLocalFileTime Lib "kernel32" _
(ByRef lpFileTime As FILETIME, ByRef lpLocalFileTime As FILETIME) As Long
Public Function LocalSystemTime(ByRef FileTimeInfo As FILETIME) As Date
Dim uLFT As FILETIME
Dim uST As SYSTEMTIME
Dim r As Long
r = FileTimeToLocalFileTime(FileTimeInfo, uft)
r = FileTimeToSystemTime(uFT, uST)
LocalSystemTime = DateSerial(uST.wYear, uST.wMonth, uST.wDay) + _
TimeSerial(uST.wHour, uST.wMinute, uST.wSecond)
End Function
Without actually trying it... here's how I'd approach it.
A system filetime is given in ticks of 100ns. Two seconds represents
2x10^7 ticks. So if two times differ by less than that, they can be
considered identical.
So first compare highparts -- if they're different then that tells the
whole story. If they're identical, subtract the lowparts and compare
the magnitude to the value representing 2 seconds. If it's less,
they're the same. If not, the sign tells you which is older.
"Jim Mack" <jm...@mdxi.nospam.com> wrote in message
news:eQWB$8biKH...@TK2MSFTNGP02.phx.gbl...
>> "Jim Mack" wrote...
>>> mp wrote:
>>>
>>> If the files are on different file systems (NTFS vs FAT, e.g.) then
>>> you can't make a guaranteed comparison of file times. The usual
>>> rule is that if file times are within two seconds, they're the same
>>> (because FAT file systems only store the time to the closest even
>>> number of seconds).
>>>
>>
>> Thanks much! hit the nail on the head...
snip
>> in some way to compute seconds?
>
> Without actually trying it... here's how I'd approach it.
>
> A system filetime is given in ticks of 100ns. Two seconds represents
> 2x10^7 ticks. So if two times differ by less than that, they can be
> considered identical.
>
> So first compare highparts -- if they're different then that tells the
> whole story. If they're identical, subtract the lowparts and compare
> the magnitude to the value representing 2 seconds. If it's less,
> they're the same. If not, the sign tells you which is older.
>
> --
> Jim Mack
> Twisted tees at http://www.cafepress.com/2050inc
> "We sew confusion"
>
Thanks much...I'll try that in a while
meanwhile last night....
after converting filetime to systemtime and comparing the struct parts I get
a variation in the DAY part!
file1
788441 year
1835009 month
42 day
0 hour
0 minute
file2
788441 year
1835009 month
22085672 day
0 hour
0 minute
I'll look at the latest suggestions,
thanks Jim and Bob
mark
Year, Month, Day, etc should all look like real year,month, and day values
so something isn't right. Either your initial filetime value is bad or you
aren't doing the conversions correctly. Maybe by year 788441 they'll have
1835009 42-day months each year but I doubt the info makes much sense
today...
Year value and its Hex representation:
788441 = 000C 07D9 (Hex)
000C (Hex) = 12 Decimal
07D9 (Hex) = 2009 Decimal
Obviously you are using Long instead of Integer when declaring SYSTEMTIME.
All members should be Integer.
Sure nuff'
don't remember where i got these defs long ago
Private Declare Function GetFileTime Lib "kernel32" (ByVal hFile As Long,
lpCreationTime As FILETIME, lpLastAccessTime As FILETIME, lpLastWriteTime As
FILETIME) As Long
Private Declare Function FileTimeToSystemTime Lib "kernel32" (lpFileTime As
FILETIME, lpSystemTime As SYSTEMTIME) As Long
Private Declare Function FileTimeToLocalFileTime Lib "kernel32" (lpFileTime
As FILETIME, lpLocalFileTime As FILETIME) As Long
Private Declare Function CompareFileTime Lib "kernel32" (lpFileTime1 As
FILETIME, lpFileTime2 As FILETIME) As Long
Private Type SYSTEMTIME
wYear As Long
wMonth As Long
wDayOfWeek As Long
wDay As Long
wHour As Long
wMinute As Long
wSecond As Long
wMilliseconds As Long
End Type
so I'll change system time type def
should the function defs also be integer instead of long?
thanks
mark
"Jim Mack" <jm...@mdxi.nospam.com> wrote in message
news:eQWB$8biKH...@TK2MSFTNGP02.phx.gbl...
not sure i've got this right...
'thanks to JimMack for this function concept
Private Function CompareFileTimes(FileTimeA As FILETIME, FileTimeb As
FILETIME, lSecondsFuzz As Long) As Long
'0 - both files same
'1 - first file newer
'2 - second file newer
'A system filetime is given in ticks of 100ns. Two seconds represents
'2x10^7 ticks. So if two times differ by less than that, they can be
'considered identical.
'
'So first compare highparts -- if they're different then that tells the
'whole story.
If FileTimeA.dwHighDateTime <> FileTimeb.dwHighDateTime Then
If FileTimeA.dwHighDateTime < FileTimeb.dwHighDateTime Then
CompareFileTimes = 2
Else
CompareFileTimes = 1
End If
Exit Function
Else
'If they're identical, subtract the lowparts and compare
'the magnitude to the value representing 2 seconds. If it's less,
'they 're the same. If not, the sign tells you which is older.
'
Dim lticks As Long
lticks = lSecondsFuzz * 10 ^ 7
If Abs(FileTimeA.dwLowDateTime - FileTimeb.dwLowDateTime) > lticks Then
If FileTimeA.dwLowDateTime < FileTimeb.dwLowDateTime Then
CompareFileTimes = 2
Else
CompareFileTimes = 1
End If
Exit Function
Else
CompareFileTimes = 0
End If
End If
End Function
i'm sure it's terrible code, but is it correct functionally?
"mp" <nos...@Thanks.com> wrote in message
news:ut8pPcwi...@TK2MSFTNGP04.phx.gbl...
It looks like it reproduces what I wrote, but it's hard to follow
because of the indenting.
To simplify it for ease of reading:
Dim Delta As Long, Diff As Long
Delta = 2 * (10^7)
If A.Hi > B.Hi Then
Result = 1
ElseIf B.Hi > A.Hi Then
Result = 2
Else
Result = 0
Diff = A.Lo - B.Lo
If Abs(Diff) > Delta Then
Select Case Sgn(Diff)
Case -1 (A - B) < 0, so B > A
Result = 2
Case 1
Result = 1
End Select
End If
End If
I think I kept your convention -- if A > B then Result = 1; if B > A
then Result = 2. Right?
BTW, I believe the high parts of FILETIMEs are equal only if the
complete times are within 7 minutes of each other, so that relatively
costly Else clause will not often be executed.
That's the theory, anyway. Still untested.
--
Jim Mack
Twisted tees at http://www.cafepress.com/2050inc
"We sew confusion"
>
> To simplify it for ease of reading:
Another simplification... (also not tested)
LFS
Function FileTimeComp(ByVal FileTimeA As FILETIME, ByVal FileTimeB As FILETIME, Optional ResolutionInSeconds As Long = 2) As
Long
Const Nano As Long = 10 ^ 7 ' 1 second using 100 nanosecond units
' CAUTION: ResolutionInSeconds causes OVERFLOW ERROR at 215+
' Return values: (Similar to StrComp)
' A < B = -1
' A = B = 0
' A > B = 1
FileTimeComp = Sgn(FileTimeA.dwHighDateTime - FileTimeB.dwHighDateTime)
If FileTimeComp = 0 Then
FileTimeA.dwLowDateTime = FileTimeA.dwLowDateTime \ (Nano * ResolutionInSeconds)
FileTimeB.dwLowDateTime = FileTimeB.dwLowDateTime \ (Nano * ResolutionInSeconds)
FileTimeComp = Sgn(FileTimeA.dwLowDateTime - FileTimeB.dwLowDateTime)
End If
End Function
is that too much indenting or too little?
> To simplify it for ease of reading:
snip
thanks
> I think I kept your convention -- if A > B then Result = 1; if B > A
> then Result = 2. Right?
right
the only reason i'm deviating from the standard -1,0,1 is i'm using
-3 = both files missing
-2 = second file missing
-1 = first file missing
0 = both files same
1 = first file newer
2 = second file newer
> BTW, I believe the high parts of FILETIMEs are equal only if the
> complete times are within 7 minutes of each other, so that relatively
> costly Else clause will not often be executed.
>
> That's the theory, anyway. Still untested.
>
> --
> Jim Mack
thanks
mark
"Larry Serflaten" <serf...@usinternet.com> wrote in message
news:%23jgZf2x...@TK2MSFTNGP05.phx.gbl...
Sure, change the convention to make it easier (-:
You might want to also handle the case where the caller wants an exact
match (ResInSec = 0)
--
Jim
Just a combination of wrapping and one-space indents. A min of two
spaces is better IMO.
When posting code it can help to indent the whole block a couple of
spaces. That way if a line wraps it's obvious, because it will start
in the undented zone.
> You might want to also handle the case where the caller wants an exact
> match (ResInSec = 0)
Doh!
That and error handling, plus the special &HFFFFFFFF condition,
(times less than zero...)
Perhaps it was a bit of over-simplification.
:-)
LFS
thanks, it looks a bit diff in the newreader than ide i think
i'm pretty sure my tabs in the ide are set to two spaces but not sure it
copied over quite right.
will check that later
mark
Bottom line -- the idea is right for languages that have unsigned
longs, but incomplete for VB.
The simplest way to handle it is to switch everything to Currency.
Then you can do direct comparison. Currency is an 8-byte integer, just
like a FILETIME, except that it's scaled by 10000.
Wherever you have "As FILETIME" in an API call or structure, just
substitute "As Currency".
Then the comparison becomes simply:
Dim Diff As Currency, Delta As Currency
Delta = 2 * (10^3) ' 10^7 scaled by 10,000
Diff = TimeA - TimeB ' all Currency vars.
Result = 0
If Diff <> 0 Then
If Abs(Diff) > Delta Then
Select Case Sgn(Diff)
Case -1
Result = 2
Case 1
Result = 1
End Select
End If
End If
Maybe there's a more clever / elegant way of dealing with all this,
and if so Larry will probably post it. (-:
"Jim Mack" <jm...@mdxi.nospam.com> wrote in message
news:uiPr$n%23iKH...@TK2MSFTNGP05.phx.gbl...
> As Larry noted, both of us were treating the low part as unsigned,
> which of course is not possible with VB Longs. So there is the
> drudgery of sign flipping or zero extension to accommodate the
> situations where it exceeds 80000000H (where it appears to go negative
> in VB).
> snip
>
> Maybe there's a more clever / elegant way of dealing with all this,
> and if so Larry will probably post it. (-:
>
> --
> Jim Mack
> Twisted tees at http://www.cafepress.com/2050inc
> "We sew confusion"
>
Thanks to everyone for these very informative and helpful gifts!
my little file comparitor class is very happy to have learned so much!!!
hope your new year is great!
thanks
mark