精确到秒的 std::time
為了獲得系統目前時間,目前 C++ 标準庫裡面給出的方法是 std::time,它傳回的結構體是 std::time_t。這個方法很友善很通用,但它有一些局限:
- 它是精确到秒的。如果您需要更高精度的時間,比如說您需要精确到毫秒,那麼它不合适。
- 它表示從 Epoch (1970年1月1日00:00:00)到現在所經過的秒數。最初 std::time_t 的定義是 32 位的,是以它的時間最多能表示到 2038年1月19日 03:14:07 (GMT時間),再過 1 秒,std::time 的傳回就會變成 1901年12月13日 20:45:52 (GMT時間)。這就是著名的 Year 2038 problem。話說 2038 年好像看起來也不太遙遠了。
- 在某些系統上(比如說我現在正在使用的Windows 7 64位),std::time_t 的定義變成了 64 位。這樣就暫時給這個函數從死刑改判成死緩了。std::time_t 的定義從 32 位改為 64 位隻是延長了它所表示的時間範圍,但并沒有改變它的精度,依然是精确到秒。
下面給出示範程式:
// GetSystemTime.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <ctime>
#include <iostream>
#define BUF_SIZE 26
int _tmain(void)
{
TCHAR buf[BUF_SIZE] = { };
errno_t err;
std::time_t cur_time;
/* Obtain current time as seconds elapsed since the Epoch. */
cur_time = std::time(nullptr);
if (cur_time == ((time_t)-))
{
fprintf_s(stderr, "Failure to compute the current time.\n");
goto EXIT;
}
/* Convert to local time format. */
err = _tctime_s(buf, BUF_SIZE, &cur_time);
if (err != )
{
_tprintf_s(_T("Invalid Arguments for _wctime_s. Error Code: %d\n"), err);
goto EXIT;
}
_tprintf_s(_T("The local time is %s\n"), buf);
EXIT:
return ;
}
執行結果:
精确到毫秒的 GetSystemTime / GetLocalTime
Windows SDK 中有兩個精确到毫秒的擷取目前時間的函數:
- GetSystemTime:擷取 UTC 時間。
- GetLocalTime:擷取當地時間。
這兩個函數的傳回都是:SYSTEMTIME
這個結構體占用了 16 個位元組,它的定義如下:
typedef struct _SYSTEMTIME {
WORD wYear;
WORD wMonth;
WORD wDayOfWeek;
WORD wDay;
WORD wHour;
WORD wMinute;
WORD wSecond;
WORD wMilliseconds;
} SYSTEMTIME, *PSYSTEMTIME;
其中 wYear 表示的範圍是:從 1601 到 30827。範圍很廣了,應該能用到天荒地老了。:-)
示範程式:
// GetSystemTime.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <Windows.h>
int _tmain(void)
{
SYSTEMTIME utc_time = { };
SYSTEMTIME local_time = { };
GetSystemTime(&utc_time);
GetLocalTime(&local_time);
_tprintf(_T("The UTC time is \t: %02d:%02d:%02d.%03d\n"), utc_time.wHour, utc_time.wMinute, utc_time.wSecond, utc_time.wMilliseconds);
_tprintf(_T("The local time is\t: %02d:%02d:%02d.%03d\n"), local_time.wHour, local_time.wMinute, local_time.wSecond, local_time.wMilliseconds);
return ;
}
運作結果:
精确到 100 納秒的 GetSystemTimeAsFileTime
究竟能不能達到 100 納秒的精确度呢?在 Windows SDK 中有一個結構體:FILETIME,它可以記錄精度達到 100ns 的時間。用哪個函數得到這個值呢?可以用 GetSystemTimeAsFileTime。
但是,不要高興得太早,雖然 FILETIME 能夠達到如此高的精度,但是這個函數我連試都懶得試。為什麼呢?因為 Windows 系統并不是一個實時作業系統(Windows Embedded Compact 2013 是一個實時系統),其時鐘精度一般認為是 15 ~ 16 毫秒。
Windows Sysinternals 給我們提供了一個檢視你使用的 Windows 系統的時鐘分辨率的小工具:ClockRes v2.0。把它下載下傳下來在控制台中執行,結果如下:
看到了吧。死心了吧。
是以說,用 GetSystemTime / GetLocalTime 就已經很好了。
如果要獲得真正毫秒級甚至更高精度的目前系統時間,必須跟 CPU 打交道,别無它法。