Windows 时间相关

           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;
}
运行效果:




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值