文件时间主要用于表示一个文件的创建时间、最后访问时间和最后修改时间。文件时间使用 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 );

标签: FILETIME, FILETIME转SYSTEMTIME, SYSTEMTIME, FILETIME格式详解, 修改文件时间

添加新评论