FILETIME 结构体的研究
文件时间主要用于表示一个文件的创建时间、最后访问时间和最后修改时间。文件时间使用 FILETIME
结构体存储,并使用Win32 API调用。
详细信息
FILETIME
结构体表示自1601年1月1日以100纳秒为基准的时间间隔。FILETIME
结构体包含2个32位的值,它们组成一个64位的值。
typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME;
注意 FILETIME
结构体是以100纳秒为基准的的时间间隔,在使用文件时间时,定义下面的宏是非常有用的。
#define _SECOND ((int64) 10000000)
#define _MINUTE (60 * _SECOND)
#define _HOUR (60 * _MINUTE)
#define _DAY (24 * _HOUR)
使用文件时间执行运算
通常使用文件时间执行一个简单的运算是必须的。例如,你可能需要知道一个文件是否已经创建超过30天了。在一个文件时间上执行运算,首先你需要将 FILETIME
转换为 quadword
(一个64字节的整形),然后执行时间运算,最后将它转回 FILETIME
类型。
假设变量 ft 是一个包含文件创建时间的 FILETIME
结构体,下面的例子演示如果在当前时间基础上增加30天。
ULONGLONG qwResult;
// Copy the time into a quadword.
qwResult = (((ULONGLONG) ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
// Add 30 days.
qwResult += 30 * _DAY;
// Copy the result back into the FILETIME structure.
ft.dwLowDateTime = (DWORD) (qwResult & 0xFFFFFFFF );
ft.dwHighDateTime = (DWORD) (qwResult >> 32 );
设置文件时间
你可以使用 SetFileTime()
函数设置文件的相关时间。
BOOL SetFileTime(
HANDLE hFile, // Handle to the file.
CONST FILETIME *lpCreationTime, // Time the file was created.
CONST FILETIME *lpLastAccessTime, // Time the file was last accessed.
CONST FILETIME *lpLastWriteTime // Time the file was last written to.
);
这个函数允许你在不改变文件内容的前提下修改文件的创建时间、最后访问时间和最后修改时间。若要使用函数,必须打开一个文件的句柄,这个文件句柄可以通过 CreateFile()
或 OpenFile()
函数获取,并且打开文件时必须使用 GENERIC_WRITE
权限。在文件时间设置完之后,你必须使用 CloseHandle()
释放句柄。
假设 szFilename
是一个有效的文件名,ft是一个 FILETIME
结构体,下面的代码演示如何设置文件的最后修改时间。
BOOL bResult;
HANDLE hFile = CreateFile( szFilename,
GENERIC_WRITE, // The file must be opened with write access.
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
if (hFile != INVALID_HANDLE_VALUE) {
bResult = SetFileTime( hFile, &ft, NULL, NULL );
CloseHandle(hFile);
}
显示文件的时间
文件时间基于协调世界时(英:Coordinated Universal Time ,法:Temps Universel Coordonné),又称世界统一时间,世界标准时间,国际协调时间。英文(CUT)和法文(TUC)的缩写不同,作为妥协,简称UTC。协调世界时是以原子时秒长为基础,在时刻上尽量接近于世界时的一种时间计量系统。
你很可能希望相对于本地时间显示文件时间(也就是当前所在时区的日期和时间)。想要显示本地时间,你可以用 FileTimeToLocalFileTime()
,如下所示:
BOOL FileTimeToLocalFileTime(
CONST FILETIME *lpFileTime, // Pointer to UTC file time to convert.
LPFILETIME lpLocalFileTime // Pointer to converted file time.
);
注意,这个函数使用当前系统设置的时区和夏令时。因此如果使用使用夏令时,这个函数能将夏令时考虑在内,即使要转换的时间是标准时间。
如果想要显示一个有意义的时间格式,你需要使用 FileTimeToSystemTime()
把 FILETIME
转换成系统时间。
BOOL FileTimeToSystemTime(
CONST FILETIME *lpFileTime, // Pointer to file time to convert.
LPSYSTEMTIME lpSystemTime // Pointer to structure to receive
);
SYSTEMTIME
使用单独的成员month、day、year、weekday、hour、minute、second 和 millisecond 表示日期和时间。
它也提供按照当前系统的本地时间格式显示日期时间。你可以使用 GetDateFormat()
和 GetTimeFormat()
,如下所示:
int GetDateFormat(
LCID Locale, // Locale for which date is to be formatted.
DWORD dwFlags, // Flags specifying function options.
CONST SYSTEMTIME *lpDate, // Date to be formatted.
LPCTSTR lpFormat, // Date format string.
LPTSTR lpDateStr, // Buffer for storing formatted string.
int cchDate // Size of buffer.
);
int GetTimeFormat(
LCID Locale, // Locale for which time is to be formatted.
DWORD dwFlags, // Flags specifying function options.
CONST SYSTEMTIME *lpTime, // Time to be formatted.
LPCTSTR lpFormat, // Time format string.
LPTSTR lpTimeStr, // Buffer for storing formatted string.
int cchTime // Size of buffer.
);
把 LOCALE_USER_DEFAULT
作为第一个参数传入这个函数,用于指定按照本地默认的是时间格式去格式化日期/时间。在这种情况下,以可以设置 lpFormat
参数为 NULL
。
假设 ft 变量是一个包含 UTC 值的 FILETIME
结构体,下面的代码演示如果格式化一个存储在 ft 变量中的日期时间。
SYSTEMTIME st;
char szLocalDate[255], szLocalTime[255];
FileTimeToLocalFileTime( &ft, &ft );
FileTimeToSystemTime( &ft, &st );
GetDateFormat( LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, szLocalDate, 255 );
GetTimeFormat( LOCALE_USER_DEFAULT, 0, &st, NULL, szLocalTime, 255 );
printf( "%s %s\n", szLocalDate, szLocalTime );