Windows的两种时间:文件时间、系统时间。相应的结构体FILETIME,SYSTEMTIME.
FILETIME结构体:
typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME, *PFILETIME;
在帮助文档中微软给出了解释:Contains a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC).即此结构体包含了一个代表自从1601年1月1日起,以100纳秒为单位的64位消逝值。
SYSTEMTIME结构体:
typedef struct _SYSTEMTIME {
WORD wYear;
WORD wMonth;
WORD wDayOfWeek;
WORD wDay;
WORD wHour;
WORD wMinute;
WORD wSecond;
WORD wMilliseconds;
} SYSTEMTIME, *PSYSTEMTIME;
解释:Specifies a date and time, using individual members for the month, day, year, weekday, hour, minute, second, and millisecond. The time is either in coordinated universal time (UTC) or local time, depending on the function that is being called.(此结构体指定日期和时间, 此时间要么是UTC时间,要么时本地时间,取决于被调用的函数)。MSDN不建议从SYSTEMTIME直接添加或提取相对时间,而是应该采用以下步骤:
1.将SYSTEMTIME转换为FILETIME
2.将FILETIME的结果拷贝到一个ULARGE_INTEGER结构体
3.在ULARGE_INTEGER上面进行64位算术运算
在WINDOWS核心编程一书上有一“等待定时器内核对象”例子。
此例会用到以下一个函数:
BOOL WINAPI SetWaitableTimer(
_In_ HANDLE hTimer,
_In_ const LARGE_INTEGER *pDueTime,
_In_ LONG lPeriod,
_In_opt_ PTIMERAPCROUTINE pfnCompletionRoutine,
_In_opt_ LPVOID lpArgToCompletionRoutine,
_In_ BOOL fResume
);
此函数的第二个参数需要一个LARGE_INTEGER的指针,此结构体如下:
typedef union _ULARGE_INTEGER {
struct {
DWORD LowPart;
DWORD HighPart;
};
struct {
DWORD LowPart;
DWORD HighPart;
} u;
ULONGLONG QuadPart;
} ULARGE_INTEGER, *PULARGE_INTEGER;
你将会发现FILETIME与此结构体拥有相同的二进制格式,你是否会想:既然这两个结构体都有相同的二进制格式,那么直接这样调用所达到的效果是不是一样呢?:
SetWaitableTimer(hTimer, (PLARGE_INTEGER)&ftUTC, 0, NULL, NULL, FALSE);
其实想是可以这么想,但千万别这么做。WINDOWS核心编程给出了答案:虽然这两个结构采用相同的二进制格式,但是这两个结构调整要求不同。所有FILETIME结构的地址必须从下一个32位边界开始,而所有LARGE_INTEGER结构的地址则必须从64位的边界开始。调用SetWaitableTimer函数和给它传递一个FILETIME结构时是否能够正确地运行,取决于FILETIME结构是否恰好位于64位的边界上。x86处理器能够悄悄地处理未对齐的数据引用。因此应用程序在x86CPU上运行时,将FILETIME的地址传递给SetWaitableTimer总是可靠的。但是,其他处理器,如Alpha处理器,则无法像x86处理器那样悄悄地处理未对齐的数据引用。实际上,大多数其它处理器都会产生一个EXCEPTION_DATATYPE_MISALIGNMENT异常,它会导致进程终止运行。当你将x86计算机上运行的代码移植到其它处理器时,产生问题的最大原因是出现了对齐错误。
可以看到SYSTEMTIME结构体里面的元素即我们平时看见的时间元素。而FILETIME结构体仅有两个32位的变量。那这两个结构体可以用来干什么呢?
FILETIME:
看到些名字就知道,此结构体必定与文件有关。you guess it.当我们创建文件,修改文件以及访问文件的时候,相应的时间就是存在此结构里面的。当然此结构体的作用不仅仅于此。此结构还经常与SYSTEMTIME之间互相转换,以达到某种目的。
SYSTEMTIME:
此结构体可供我们用来打印具体的时间。经常与FILETIME相互转换,以达到某种目的。
相关的函数:
void WINAPI GetSystemTime( //得到系统(UTC时间)时间
_Out_ LPSYSTEMTIME lpSystemTime
);
void WINAPI GetLocalTime( // 得到本地时间
_Out_ LPSYSTEMTIME lpSystemTime
);
BOOL WINAPI SystemTimeToFileTime( // 系统时间转换为文件时间
_In_ const SYSTEMTIME *lpSystemTime,
_Out_ LPFILETIME lpFileTime
);
BOOL WINAPI FileTimeToSystemTime( //文件时间转换为系统时间
_In_ const FILETIME *lpFileTime,
_Out_ LPSYSTEMTIME lpSystemTime
);
BOOL WINAPI LocalFileTimeToFileTime( //本地时间转换为文件时间
_In_ const FILETIME *lpLocalFileTime,
_Out_ LPFILETIME lpFileTime
);
BOOL FileTimeToLocalFileTime( //文件时间转换为本地文件时间
const FILETIME* lpFileTime,
LPFILETIMElpLocalFileTime
);
BOOL WINAPI SystemTimeToTzSpecificLocalTime( //UTC时间转换为特定时区时间
_In_opt_ LPTIME_ZONE_INFORMATION lpTimeZone,
_In_ LPSYSTEMTIME lpUniversalTime,
_Out_ LPSYSTEMTIME lpLocalTime
);
INT SystemTimeToVariantTime( //Converts a system time to a variant representation.
_In_ LPSYSTEMTIME lpSystemTime,
_Out_ DOUBLE *pvtime
);
......
下面的例子用到了前面几个函数:
#include <windows.h>
#include <iostream>
void printTime(FILE *file, PCSTR pszDesc, const SYSTEMTIME &st){
fprintf_s(file, ("%s : %ld/%02d/%02d %02d:%02d:%02d\n"),
pszDesc, st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
}
int main(){
SYSTEMTIME st;
FILETIME ft, ftUTC;
// get UTC time
GetSystemTime(&st);
printTime(stdout, ("UTC 时间"), st);
// convert UTC time to file time
SystemTimeToFileTime(&st, &ft);
FileTimeToLocalFileTime(&ft, &ftUTC);
// convert file time to system time
FileTimeToSystemTime(&ftUTC, &st);
printTime(stdout, ("系统时间"), st);
HANDLE hFile;
TCHAR szFile[] = TEXT("C:\\Users\\Eternal\\Desktop\\3D俄罗斯方块\\3Dtetries\\Debug\\3Dtetries.exe");
hFile = CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING , NULL, 0);
if(hFile == INVALID_HANDLE_VALUE){
std::cout << "accessing file failed" << std::endl;
return EXIT_FAILURE;
}
std::cout << "\n文件:3Dtetries.exe" << std::endl;
FILETIME ftCreate, ftAccess, ftLastWrite;
GetFileTime(hFile, &ftCreate, &ftAccess, &ftLastWrite);
FileTimeToSystemTime(&ftCreate, &st);
printTime(stdout, ("创建时间"), st);
FileTimeToSystemTime(&ftAccess, &st);
printTime(stdout, ("访问时间"), st);
FileTimeToSystemTime(&ftLastWrite, &st);
printTime(stdout, ("修改时间"), st);
return 0;
}
运行效果: