计算机中的时间
做专业的程序员
计算机计时原理
GMT
时间(Greenwich Mean Time
),即格林威治标准时间
,正午太阳横穿格林威治子午线的时间。UTC
时间(Universal Time Coordinated
),即世界调整时间
,由原子钟计时,根据GMT
校准后得到的时间。CST
时间(Central Standard Time
),即中央标准时间
,可视为美国
,澳大利亚
,古巴
或中国
的标准时间:
- 美国中部时间:Central Standard Time (USA) UT-6:00
- 澳大利亚中部时间:Central Standar Time (Australia) UT+9:30
- 中国标准时间:Chian Standard Time UT+8:00
- 古巴标准时间:Cuba Standar Time UT -4:00
自1924年2月5日开始,格林威治天文台每隔一小时会向全世界发放调时信息。
原子钟
是一种时钟,以原子共振频率标准来计算及保持时间的准确【电子转变能级时释放的精确微波信号】。原子钟是世界上已知最准确的时间测量和频率标准,也是国际时间和频率转换的标准。
FILETIME与UNIX时间转换
不同操作系统的计时起点:
- Linux/Unix 1970-1-1 00:00:00 【考虑时区,北京时间:1970-1-1 08:00:00】
- Windows 1601-1-1 00:00:00 【11644473600LL seconds before Linux/Unix epoch】
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38typedef struct _FILETIME
{
DWORD dwLowDateTime; // low 32 bits
DWORD dwHighDateTime; // high 32 bits
}FILETIME, *PFILETIME, *LPFILETIME;
typedef union _ULARGE_INTEGER
{
struct
{
DWORD LowPart;
DWORD HighPart;
};
struct
{
DWORD LowPart;
DWORD HighPart;
}u;
ULONGLONG QuadPart;
}ULARGE_INTEGER, *PULARGE_INTEGER;
FILETIME fileTime; // 时钟嘀嗒,100ns,开始于 1601-01-01 00:00:00
// 移位操作
unsigned long long ulongTime = fileTime.dwHighDateTime;
ulongTime = ulongTime << 32 | fileTime.dwLowDateTime;
// 官方推荐
ULARGE_INTEGER ulargeTime;
ulargeTime.HighPart = fileTime.dwHighDateTime;
ulargeTime.LowPart = fileTime.dwLowDateTime;
// 转换
// 1601-01-01 00:00:00 与 1970-01-01 00:00:00 间隔的秒数
time_t unixTime1 = ulongTime / WINDOWS_TICK - SEC_TO_UNIX_EPOCH;
time_t unixTime2 = ulargeTime.QuadPart / WINDOWS_TICK - SEC_TO_UNIX_EPOCH;
获取当前系统时间
- time_t 时间戳,距离 1900-01-01 00:00:00 的秒数。
1
2
3
4time_t time(time_t *timer);
timer --> Pointer to the storage location for time.
Return Value --> Return the time as seconds elapsed since midnight, January 1,1970,
or -1 in the case of an error. - tm 精确到秒的时间结构体,需注意各成员的取值范围。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25struct tm
{
int tm_sec; // the number of seconds [0-59]
int tm_min; // the number of minutes [0-59]
int tm_hour; // the number of hours since midnight [0-23]
int tm_mday; // indicate the day of the month [1-31]
int tm_mon; // the number of months since January [0-11]
int tm_year; // the number of years since 1900 [117 --> 1900+117=2017]
int tm_wday; // the number of days since Sundary [0-6]
int tm_yday; // the number of days since January 1 [0-365]
int tm_isdst; // daylight savings time [TRUE] and normal time [FALSE]
};
tm m_tmCurTime;
time_t m_tCurTime;
time(&m_tCurTime);// 当前时间戳
// 根据当前所在时区(系统设置)转换为信息全面的结构
localtime_s(&m_tmCurTime, &m_tCurTime);
long timeZoneOffset;
time_t tempTime;
_tzset();
_get_timezone(&timeZoneOffset);
tempTime = m_tCurTime - timeZoneOffset;
gmtime_s(&m_tmCurTime, &tempTimeOB);// 标准时间,需要根据时区自行调整(参见后文 时区) - SYSTEMTIME
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17typedef struct _SYSTEMTIME
{
WORD wYear; // The current year.
WORD wMonth; // The current month; January is 1.
WORD wDayOfWeek; // The current day of the week; Sunday is 0, Monday is 1, and so on.
WORD wDay; // The current day of the month.
WORD wHour; // The current hour.
WORD wMinute; // The current minute.
WORD wSecond; // The current second.
WORD wMilliseconds; // The current millisecond.
} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME;
SYSTEMTIME m_systemTime;
::GetLocalTime(&m_systemTime);
char timeBuffer[64];
sprintf_s(timeBuffer, "%4d-%02d-%02d %02d:%02d:%02d.%03d",
m_systemTime.wYear, m_systemTime.wMonth, m_systemTime.wDay,
m_systemTime.wHour, m_systemTime.wMinute, m_systemTime.wSecond, m_systemTime.wMilliseconds);
时区与时间差
- 时差 UTC = LocalTime + Bias
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23time_t timeTest;
time(&timeTest);
tm gmTime;
tm loTime;
gmtime_s(&gmTime, &timeTest);
time_t gmt = mktime(&gmTime);
localtime_s(&loTime, &timeTest);
time_t lot = mktime(&loTime);
double diff = difftime(gmt, lot);// -28800.000000
long timeZone;
// The _get_timezone function retrieves the difference in seconds
// between UTC and local time as an integer.
// The default value is 28,800 seconds, for Pacific Standard Time (eight hours behind UTC).
int errorCode = _get_timezone(&timeZone);// -28800(28800)
char timeZoneName[64];
size_t t;
_get_tzname(&t, timeZoneName, sizeof(timeZoneName), 0);// 中国标准时间(太平洋标准时间)
// 通过调整系统时间可知:
// 中国标准时间 = -28800
// 太平洋标准时间 = 28800
// _get_timezone = 格林威治时间 - 本地时间 - 获取时区相关信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28// set time environment variables:
// assign values to three global variables:_daylignt,_timezone and _tzname
_tzset();
int dayLightHours; // 以小时为单位的日光节约时间
long dayLightSeconds; // 以秒为单位的日光节约时间
long timeZone; // 秒数 = 格林威治时间 - 本地时间
char timeZoneName[64]; // 时区名称
size_t nameLen; // 时区名称长度,包括终结符
_get_daylight(&dayLightHours);// daylight saving time offset in hours
_get_dstbias(&dayLightSeconds);// daylight saving time offset in seconds
int errorCode = _get_timezone(&timeZone);
_get_tzname(&nameLen, timeZoneName, sizeof(timeZoneName), 0);
// This structure specifies information specific to the time zone.
typedef struct _TIME_ZONE_INFORMATION
{
LONG Bias;
WCHAR StandardName[32];
SYSTEMTIME StandardDate;
LONG StandardBias;
WCHAR DaylightName[32];
SYSTEMTIME DaylightDate;
LONG DaylightBias;
} TIME_ZONE_INFORMATION;
TIME_ZONE_INFORMATION timeZoneInfo;
GetTimeZoneInformation(&timeZoneInfo);
精确计算时间差
- QueryPerformanceFrequency
1
2
3
4
5
6
7
8
9
10
11BOOL QueryPerformanceFrequency(LARGE_INTEGER* lpFrequency);
This function retrieves the frequency of the high-resolution performance counter
if one is provided by the OEM.
lpFrequency -->
[out] Pointer to a variable that the function sets, in counts per second,
to the current performance-counter frequency.
If the installed hardware does not support a high-resolution performance counter,
the value passed back through this pointer can be zero.
Return Value -->
TRUE indicates that a performance frequency value was successfully filed in.
False indicates failure. - QueryPerformanceCounter
1
2
3
4
5
6
7
8
9
10
11BOOL QueryPerformanceCounter(LARGE_INTEGER* lpPerformanceCount);
This function retrieves the current value of the high-resolution performance counter
if one is provided by the OEM.
lpPerformanceCount -->
[in] Pointer to a variable that the function sets, in counts,
to the current performance-counter value.
If the installed hardware does not support a high-resolution performance counter,
this parameter can be set to zero.
Return Value -->
TRUE indicates that a performance counter value was successfully filled in.
FALSE indicates failure. - GetTickCount
1
2
3
4
5DWORD WINAPI GetTickCount(void);
Retrieves the number of milliseconds that have elapsed since the system was started,
up to 49.7 days.
Return Value -->
The return value is the number of milliseconds that have elapsed since the system was started. - clock
1
2
3
4
5
6clock_t clock( void );
Calculates the wall-clock time used by the calling process.
Return Value -->
The elapsed wall-clock time since the start of the process
(elapsed time in seconds times CLOCKS_PER_SEC).
If the amount of elapsed time is unavailable, the function returns –1, cast as a clock_t.
CPP 标准库时间
1 | typedef ratio<1, 1000000000000000000000000LL> yocto; // 有条件的支持 |