Re: Other information and dates of an archive
- Posted by OtterDad <otter at full-moon.com> Feb 07, 2007
- 589 views
[snipped code] i couldn't help but keep trying at this code, if nothing else but for my own education. i wrapped the FileTimeToLocalFileTime function, which handles all the time zone, daylight savings time, time bias, etc. for you. i also added the windows api documentation more for my benefit. i tried to leave the original coding style in place to not confuse the original author.
-- gather other time stamp info from files. based on code posted to the forum: -- Date: 2007 Feb 5 15:35 -- From: CChris <christian.cuvier at agriculture.gouv.fr> -- Subject: Re: Other information and dates of an archive -- API documentation and FileTimeToLocalFileTime added by OtterDad without warning include win32lib.ew sequence fname, creation, lastAccess, updated, local_creation, local_lastAccess, local_updated atom hfile, year, month, dow, day, hour, min, sec, msec integer return_code fname = "C:\\ex.err" fname = "C:\\boot.ini" -- set this to the actual file name ----------------------------------------------------------------------------- procedure wwait(object messag ) atom result, rr rr = getSelf() if sequence (messag) then result = message_box(messag , "Message !", MB_ICONEXCLAMATION + MB_TASKMODAL) else result = message_box(sprintf( "%d\n", messag), "Message !", MB_ICONEXCLAMATION + MB_TASKMODAL) end if -- setFocus(rr) end procedure ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- procedure makeDate(sequence field, object data) -- reads and translates a SYSTEMTIME structure year = peek(data + 0) + (peek(data + 1) * 256) month = peek(data + 2) + (peek(data + 3) * 256) dow = peek(data + 4) + (peek(data + 5) * 256) day = peek(data + 6) + (peek(data + 7) * 256) hour = peek(data + 8) + (peek(data + 9) * 256) min = peek(data + 10) + (peek(data + 11) * 256) sec = peek(data + 12) + (peek(data + 13) * 256) msec = peek(data + 14) + (peek(data + 15) * 256) if match(field, "system_create_time") then creation = sprintf("%04d/%02d/%02d %02d:%02d:%02d", {year, month, day, hour, min, sec}) elsif match(field, "system_last_access") then lastAccess = sprintf("%04d/%02d/%02d %02d:%02d:%02d", {year, month, day, hour, min, sec}) elsif match(field, "system_last_write") then updated = sprintf("%04d/%02d/%02d %02d:%02d:%02d", {year, month, day, hour, min, sec}) elsif match(field, "local_system_create_time") then local_creation = sprintf("%04d/%02d/%02d %02d:%02d:%02d", {year, month, day, hour, min, sec}) elsif match(field, "local_system_last_access") then local_lastAccess = sprintf("%04d/%02d/%02d %02d:%02d:%02d", {year, month, day, hour, min, sec}) elsif match(field, "local_system_last_write") then local_updated = sprintf("%04d/%02d/%02d %02d:%02d:%02d", {year, month, day, hour, min, sec}) end if end procedure ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- -- wrap a few functions from kernel32.dll constant kernel32 = open_dll("kernel32.dll"), GetFileTime = define_c_func(kernel32, "GetFileTime", repeat(C_POINTER, 4), C_LONG), -- GetFileTime 11/30/2006 -- This function retrieves the date and time that a file was created, last accessed, and last modified. -- Syntax -- BOOL GetFileTime(HANDLE hFile, LPFILETIME lpCreationTime, LPFILETIME lpLastAccessTime, -- LPFILETIME lpLastWriteTime ); -- Parameters -- hFile - [in] Handle to the files for which to get dates and times. The file handle must have been -- created with GENERIC_READ access to the file. -- lpCreationTime - [out] Pointer to a FILETIME structure to receive the date and time the file was created. -- This parameter can be NULL if the application does not require this information. -- lpLastAccessTime - [out] Pointer to a FILETIME structure to receive the date and time the file was last -- accessed. The last access time includes the last time the file was written to, read from, or, in the -- case of executable files, run. This parameter can be NULL if the application does not require this -- information. -- lpLastWriteTime - [out] Pointer to a FILETIME structure to receive the date and time the file was last -- written to. This parameter can be NULL if the application does not require this information. -- Return Value -- Nonzero indicates success. -- Zero indicates failure. -- Remarks -- The FAT and NTFS file systems support the file creation, last access, and last write time values. -- The Windows Embedded CE object store returns the same creation time value for all three parameters. -- In general, file system drivers will vary how they support this function. The precision of the time -- for a file in a FAT file system is one second. The time precision for files in other file systems, -- such as those connected through a network or installed on a peripheral device, depends on the file -- system but may also be limited by the target device. -- Requirements -- Header: Winbase.h. -- Link Library: Coredll.lib. -- FILETIME -- Contains a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC). -- typedef struct _FILETIME { DWORD dwLowDateTime; DWORD dwHighDateTime; -- } FILETIME, *PFILETIME; -- Members -- dwLowDateTime - The low-order part of the file time. -- dwHighDateTime - The high-order part of the file time. -- Remarks -- To convert a FILETIME structure into a time that is easy to display to a user, use the -- FileTimeToSystemTime function. -- It is not recommended that you add and subtract values from the FILETIME structure to obtain -- relative times. Instead, you should: -- Copy the resulting FILETIME structure to a ULARGE_INTEGER structure using memcpy (using memcpy -- instead of direct assignment can prevent alignment faults on 64-bit Windows). -- Use normal 64-bit arithmetic on the ULARGE_INTEGER value. -- 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. FileTimeToSystemTime = define_c_func(kernel32, "FileTimeToSystemTime", repeat(C_POINTER, 2), C_LONG), -- Converts a file time to system time format. -- BOOL FileTimeToSystemTime( -- const FILETIME* lpFileTime, -- LPSYSTEMTIME lpSystemTime -- ); -- Parameters -- lpFileTime - [in] A pointer to a FILETIME structure containing the file time to convert to system date -- and time format. This value must be less than 0x8000000000000000. Otherwise, the function fails. -- lpSystemTime - [out] A pointer to a SYSTEMTIME structure to receive the converted file time. -- Return Value -- If the function succeeds, the return value is nonzero. -- If the function fails, the return value is zero. To get extended error information, call GetLastError. -- SYSTEMTIME - 11/30/2006 -- This structure represents a date and time using individual members for the month, day, year, weekday, -- hour, minute, second, and millisecond. -- Syntax -- typedef struct _SYSTEMTIME { -- WORD wYear; -- WORD wMonth; -- WORD wDayOfWeek; -- WORD wDay; -- WORD wHour; -- WORD wMinute; -- WORD wSecond; -- WORD wMilliseconds; -- } SYSTEMTIME; -- Members -- wYear - Specifies the current year. -- wMonth - Specifies the current month; January = 1, February = 2, and so on. -- wDayOfWeek - Specifies the current day of the week; Sunday = 0, Monday = 1, and so on. -- wDay - Specifies the current day of the month. -- wHour - Specifies the current hour. -- wMinute - Specifies the current minute. -- wSecond - Specifies the current second. -- wMilliseconds - Specifies the current millisecond. -- Remarks -- Millisecond granularity may not be supported by a hardware platform. The caller of this function should -- not rely on more than second granularity. -- It is not recommended that you add and subtract values from this structure to obtain relative times. -- The following list shows tasks to perform instead: -- Convert the SYSTEMTIME structure to a FILETIME structure. -- Copy the resulting FILETIME structure to a ULARGE_INTEGER structure. -- Use usual 64-bit arithmetic on the ULARGE_INTEGER value. -- Requirements -- Header: Winbase.h. FileTimeToLocalFileTime = define_c_func(kernel32, "FileTimeToLocalFileTime", repeat(C_POINTER, 2), C_LONG), -- Converts a file time to a local file time. -- BOOL FileTimeToLocalFileTime( -- const FILETIME* lpFileTime, -- LPFILETIME lpLocalFileTime -- ); -- Parameters -- lpFileTime - [in] A pointer to a FILETIME structure containing the UTC-based file time to be -- converted into a local file time. -- lpLocalFileTime - [out] A pointer to a FILETIME structure to receive the converted local file time. -- This parameter cannot be the same as the lpFileTime parameter. -- Return Value -- If the function succeeds, the return value is nonzero. -- If the function fails, the return value is zero. To get extended error information, call GetLastError. -- Remarks -- FileTimeToLocalFileTime uses the current settings for the time zone and daylight saving time. -- Therefore, if it is daylight saving time, this function will take daylight saving time into account, -- even if the time you are converting is in standard time. You can use the following sequence of functions -- as an alternative. -- FileTimeToSystemTime -- SystemTimeToTzSpecificLocalTime -- SystemTimeToFileTime CreateFileA = define_c_func(kernel32, "CreateFileA", repeat(C_POINTER, 7), C_POINTER), CloseHandle = define_c_func(kernel32, "CloseHandle", {C_POINTER}, C_LONG), GetTimeZoneInformation = define_c_func(kernel32, "GetTimeZoneInformation", {C_POINTER}, C_ULONG), -- GetTimeZoneInformation -- This function retrieves the current time-zone parameters. These parameters control the translations -- between UTC and local time. -- DWORD GetTimeZoneInformation( LPTIME_ZONE_INFORMATION lpTimeZoneInformation ); -- Parameters -- lpTimeZoneInformation - [out] Pointer to a TIME_ZONE_INFORMATION structure to receive the current -- time-zone parameters. -- Return Values -- If the function succeeds, the return value is one of the following values: -- Value Description -- TIME_ZONE_ID_UNKNOWN = 0 The system cannot determine the current time zone. If daylight saving -- time is not used in the current time zone, this value is returned because there are no -- transition dates. -- TIME_ZONE_ID_STANDARD = 1 The system is operating in the range covered by the StandardDate member -- of the TIME_ZONE_INFORMATION structure. -- TIME_ZONE_ID_DAYLIGHT = 2 The system is operating in the range covered by the DaylightDate member -- of the TIME_ZONE_INFORMATION structure. -- If the function fails, the return value is TIME_ZONE_ID_UNKNOWN. -- Remarks -- All translations between UTC and local time are based on the following formula. -- UTC = local time + bias -- The bias is the difference, in minutes, between UTC and local time. -- If a call to SetTimeZoneInformation supplies a bias value but no transition date, -- GetTimeZoneInformation will return either TIME_ZONE_ID_STANDARD or TIME_ZONE_ID_DAYLIGHT. -- Requirements -- Header: Winbase.h. -- Link Library: Coredll.lib. TIME_ZONE_ID_UNKNOWN = 0, TIME_ZONE_ID_STANDARD = 1, TIME_ZONE_ID_DAYLIGHT = 2, -- reserving some memory mem_area = allocate(72 + 24 + 48), -- area for FILETIME raw data file_create_time = mem_area, file_last_access = mem_area+8, file_last_write = mem_area+16, -- area for local FILETIME raw data local_file_create_time = mem_area+24, local_file_last_access = mem_area+32, local_file_last_write = mem_area+40, -- area for SYSTEMTIME usable data system_create_time = mem_area+48, system_last_access = mem_area+64, system_last_write = mem_area+80, -- area for local SYSTEMTIME usable data local_system_create_time = mem_area+96, local_system_last_access = mem_area+112, local_system_last_write = mem_area+128, -- this flag is used later: it tells the OS to fail upon opening a file -- whiCloseHandle doesn't exist OPEN_EXISTING = 3, -- and get some storage for a TIME_ZONE_INFO structure TimeZoneInformation = allocate(172) integer bias, std_bias, svt_bias, TIME_ZONE_ID -- fill the structure TIME_ZONE_ID = c_func(GetTimeZoneInformation, {TimeZoneInformation}) -- rc may be an error code, or say if we are in std time, xaving time or don't know bias = peek4s(TimeZoneInformation) --warnErr(sprint(TIME_ZONE_ID) & " " & sprint(bias)) std_bias = bias+peek4s(TimeZoneInformation+84) -- usually = bias svt_bias = bias+peek4s(TimeZoneInformation+168) -- free memory free(TimeZoneInformation) -- set hfile to a handle on your file hfile = c_func(CreateFileA, {allocate_string(fname), 0, 0, 0, OPEN_EXISTING, 0, 0}) if not hfile then -- something went wrong, do something useful here warnErr("can't open " & fname) abort(1) end if -- now we have a file handle, let's get the timestamps -- you may wish to Check if return_code = 0, which notifies of an error return_code = c_func(GetFileTime, {hfile, file_create_time, file_last_access, file_last_write}) -- convert the data to something of use. Again, return_code = 0 means something went wrong return_code = c_func(FileTimeToSystemTime, {file_create_time, system_create_time}) makeDate("system_create_time", system_create_time) return_code = c_func(FileTimeToSystemTime, {file_last_access, system_last_access}) makeDate("system_last_access", system_last_access) return_code = c_func(FileTimeToSystemTime, {file_last_write, system_last_write}) makeDate("system_last_write", system_last_write) wwait(sprintf("modified = %s \ncreation = %s \nlastAccess = %s", {updated, creation, lastAccess})) -- now convert to local time return_code = c_func(FileTimeToLocalFileTime, {file_create_time, local_file_create_time}) return_code = c_func(FileTimeToSystemTime, {local_file_create_time, local_system_create_time}) makeDate("local_system_create_time", local_system_create_time) return_code = c_func(FileTimeToLocalFileTime, {file_last_access, local_file_last_access}) return_code = c_func(FileTimeToSystemTime, {local_file_last_access, local_system_last_access}) makeDate("local_system_last_access", local_system_last_access) return_code = c_func(FileTimeToLocalFileTime, {file_last_write, local_file_last_write}) return_code = c_func(FileTimeToSystemTime, {local_file_last_write, local_system_last_write}) makeDate("local_system_last_write", local_system_last_write) wwait(sprintf("modified = %s \ncreation = %s \nlastAccess = %s", {local_updated, local_creation, local_lastAccess})) return_code = c_func(CloseHandle, {hfile})
Yours, OtterDad Don't sweat it -- it's not real life. It's only ones and zeroes. Gene Spafford