格林尼治时间
格林尼治时间亦称“世界时”。格林尼治所在地的标准时间。现在不光是天文学家使用格林尼治时间,就是在新闻报刊上也经常出现这个名词。我们知道各地都有各地的地方时间。如果对国际上某一重大事情,用地方时间来记录,就会感到复杂不便,而且将来日子一长容易搞错。因此,天文学家就提出一个大家都能接受且又方便的记录方法,那就是以格林尼治的地方时间为标准。格林尼治是英国伦敦南郊原格林尼治天文台的所在地,它又是世界上地理经度的起始点。对于世界上发生的重大事件,都以格林尼治的地方时间记录下来。一旦知道了格林尼治时间,人们就很容易推算出相当的本地时间。例如,某事件发生在格林尼治时间上午8时,我国在英国东面,北京时间比格林尼治时同要早8小时,我们就立刻知道这次事情发生在相当于北京时间16时,也就是北京时间下午4时。
POSIX时间
我们人类使用的计时系统是相当复杂的:秒是基本单位, 60秒为1分钟, 60分钟为1小时, 24小时是一天......如果计算机也使用相同的方式来计时, 那显然就要用多个变量来分别存放年月日时分秒, 不停的进行进位运算, 而且还要处理偶尔的闰年和闰秒以及协调不同的时区. 基于"追求简单"的设计理念, UNIX在内部采用了一种最简单的计时方式:计算从UNIX诞生的UTC时间1970年1月1日0时0分0秒起, 流逝的秒数. UTC时间1970年1月1日0时0分0秒就是UNIX时间0, UTC时间1970年1月2日0时0分0秒就是UNIX时间86400. 这个计时系统被所有的UNIX和UNIX-like系统继承了下来, 而且影响了许多非UNIX系统. POSIX标准推出后, 这个时间也被称为POSIX时间。
国际原子时
国际原子时(TAI):针对某些元素的原子能级跃迁频率有极高的稳定性,可采用基于铯原子(Cs 132.9)的能级跃迁原子秒作为时标。国际计量局(BIPM)根据世界20多个国家的实验室的100多台原子钟提供的数据进行处理,得出“国际时间标准”称为国际原子时(TAI)。原子时秒长的定义是:铯133原子基态的两个超精细能级间在零磁场下跃迁辐射周期 9,192,631,770倍所持续的时间。1967年第十三届国际计量委员会决定,把在海平面上实现的上述原子时秒,规定为国际单位制时间单位。从此,时间计量标准便正式由天文学的宏观领域过渡到了物理学的微观领域。
协调世界时
国际原子时的准确度为每日数纳秒,而世界时的准确度为每日数毫秒。对于这种情况,一种称为协调世界时的折衷时标于1972年面世。为确保协调世界时与世界时相差不会超过0.9秒,在有需要的情况下会在协调世界时内加上正或负闰秒。因此协调世界时与国际原子时之间会出现若干整数秒的差别。位于巴黎的国际地球自转事务中央局负责决定何时加入闰秒。一般会在每年的6月30日、12月31日的最后一秒进行调整。
平太阳时
也就是我们日常生活中所使用的时间。太阳连续两次经过上中天的时间间隔,称为真太阳日。我们知道,地球沿着椭圆形轨道运动的,太阳位于该椭圆的一个焦点上,因此,在一年中,日地距离不断改变。根据开普勒第二定律,行星在轨道上运动的方式是它和太阳所联结的直线在相同时间内所划过的面积相等,可见,地球在轨道上做的是不等速运动,这样一来,一年之内真太阳日的长度便不断改变,不易选做计时单位,于是引进平太阳的概念。天文学上假定由一个太阳(平太阳)在天赤道上(而不是在黄赤道上)作等速运行,其速度等于运行在黄赤道上真太阳的平均速度,这个假想的太阳连续两次上中天的时间间隔,叫做一个平太阳日,这也相当于把一年中真太阳日的平均称为平太阳日,并且把1/24平太阳日取为1平太阳时。通常所谓的“日”和“时”,就是平太阳日和平太阳时的简称。
在标准C/C++中,最小的计时单位是一毫秒。
结构体介绍:
FILETIME
FILETIME结构持有的64位无符号的文件的日期和时间值。此值表示自1601年1月1日开始的100纳秒为单位的时间。
语法typedef struct _FILETIME {
DWORD dwLowDateTime; /* 低 32 位 */
DWORD dwHighDateTime; /* 高 32 位 */
} FILETIME, *PFILETIME, *LPFILETIME;
SYSTEMTIME
STRUCT
{
WORD wYear ; 年
WORD wMonth ;月
WORD wDayOfWeek ;星期,0=星期日,1=星期一...
WORD wDay ;日
WORD wHour ;时
WORD wMinute ;分
WORD wSecond ;秒
WORD wMilliseconds ;毫秒
}SYSTEMTIME ENDS
函数介绍:
asctime()
功能:转换日期和时间为相应的字符串(英文简写形式)。
clock()
功能:这个函数返回从“开启这个程序进程”到“程序中调用clock()函数”时之间的CPU时钟计时单元(clock tick)数,毫秒级。
clock_t的定义如下:
#ifndef _CLOCK_T_DEFINED
typedef long clock_t;
#define _CLOCK_T_DEFINED
#endif
ftime()
int ftime(struct timeb *tp);获取当前时间,并将其保存在结构体timeb中
struct timeb{
time_t time;
unsigned short millitm;
short timezonel;
short dstflag;
};
timeb.time
为1970-01-01至今的秒数
timeb.millitm
微秒
timeb.timezonel
为目前时区和Greenwich相差的时间,单位为分钟
timeb.dstflag
为日光节约时间的修正状态,如果为非0代表启用日光节约时间修正
GetSystemTimeAsFileTime()
Retrieves the current system date and time. The information is in Coordinated Universal Time (UTC) format.
例:
FILETIME st;
GetSystemTimeAsFileTime(&st);
SystemTimeToFileTime()
SYSTEMTIME stLocal, stUTC, stUTC2;
FILETIME ftLocal, ftUTC, ft;
ULARGE_INTEGER uli;
GetLocalTime(&stLocal);
GetSystemTime(&stUTC);
printf("Local System Time(YYYY-MM-DD HH:MM:SS): %d-%d-%d %d:%d:%d/n", stLocal.wYear, stLocal.wMonth,
stLocal.wDay, stLocal.wHour, stLocal.wMinute, stLocal.wSecond);
printf("UTC System Time (YYYY-MM-DD HH:MM:SS): %d-%d-%d %d:%d:%d/n", stUTC.wYear,
stUTC.wMonth, stUTC.wDay, stUTC.wHour, stUTC.wMinute, stUTC.wSecond);
SystemTimeToFileTime(&stLocal, &ftLocal);
GetCurrentTime
CTime time=CTime::GetCurrentTime();
st=time.Format("%Y-%m-%d-%H-%M-%S");
GetLocalTime()
功能:获取的是国际标准时间也就是格林尼治时间。
参数说明: lpSystemTime: 指向一个用户自定义包含日期和时间信息的类型为 SYSTEMTIME 的变量,该变量用来保存函数获取的时间信息。 此函数会把获取的系统时间信
息存储到SYSTEMTIME结构体里边 typedef struct _SYSTEMTIME { WORD wYear;//年 WORD wMonth;//月 WORD wDayOfWeek;//星期,0为星期日,1为星期一,
2为星期二…… WORD wDay;//日 WORD wHour;//时 WORD wMinute;//分 WORD wSecond;//秒 WORD wMilliseconds;//毫秒 }SYSTEMTIME,*PSYSTEMTIME;
GetSystemTime()
功能:获取的是你所在的时区的时间,例如北京时间。
GetTickCount()
功能:函数功能:GetTickCount返回(retrieve)从操作系统启动到现在所经过(elapsed)的毫秒数,它的返回值是DWORD,在49.7天之后会溢出从0开始计了。
gettimeofday()
#include <sys/time.h> int gettimeofday(struct timeval *tv, struct timezone *tz);
linux下获取时间的函数,其参数tv是保存获取时间结果的结构体,参数tz用于保存时区结果(若不使用则传入NULL即可)。
结构体timeval的定义为:
struct timeval {
long tv_sec; // 秒数
long tv_usec; // 微秒数
}
它获得的时间精确到微秒(1e-6 s)量级。在一段代码前后分别使用gettimeofday可以计算代码执行时间。
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
int main()
{
struct timeval dwStart;
struct timeval dwEnd;
unsigned long dwTime=0;
int i=0,j=0;
gettimeofday(&dwStart,NULL);
for(i=0;i<100000;i++) { ; }
gettimeofday(&dwEnd,NULL);
dwTime = 1000000*(dwEnd.tv_sec-dwStart.tv_sec)+(dwEnd.tv_usec-dwStart.tv_usec);
printf("%ld/n",dwTime);
return 0;
}
localtime()
功能:把从1900-1-1零点零分到当前时间系统所偏移的秒数时间转换为日历时间 。例:
...
time_t timer;//time_t就是long int 类型
struct tm *tblock;
timer = time(NULL);
tblock = localtime(&timer);
printf("Local time is: %s\n",asctime(tblock));
return 0;
...
执行结果: Local time is: Mon Feb 16 11:29:26 2009
mktime()
功能:用来将参数timeptr所指的tm结构数据转换成从公元1970年1月1日0时0分0 秒算起至今的UTC(世界统一时间)时间所经过的秒数。
QueryPerformanceCounter()
The QueryPerformanceCounter function retrieves the current value of the high-resolution performance counter, ifone exists。如果安装的硬件支持高精度计时器,函数将返回非0值.如果安装的硬件不支持高精度计时器,函数将返回0。
例:LARGE_INTEGER tickNow; QueryPerformanceCounter(&tickNow);
time()
功能:返回自1970年1月1日到目前所经过的秒数,其参数是一个指向long对象的指针,如果提供了这样一个指针,返回的秒数将保存在这个对象中,如果是NULL表示不保存,只由
函数的返回值返回。time的参数跟返回值是一样的。
例:
cout<<time(0);
值约为1169174701,约等于37(年)乘365(天)乘24(小时)乘3600(秒)(月日没算)。
timeSetEvent()
一种精确度非常高的定时器,与windows定时器不同的是,多媒体定时器不使用容易丢失的窗口消息,他提供另外两种方式来触发。
MMRESULT timeSetEvent(UINT uDelay,UINT uResolution,LPTIMECALLBACK lpTimeProc,DWORD_PTR dwUser,UINT fuEvent);
Parameters
uDelay
Event delay, in milliseconds. If this value is not in the range of the minimum and maximum event delays supported by the timer, the function returns an
error.
事件延迟,毫秒。如果这个值不在定时器支持的最小和最大延时之间的话,函数将返回一个错误。
uResolution
Resolution of the timer event, in milliseconds. The resolution increases with smaller values; a resolution of 0 indicates periodic events should occur with
the greatest possible accuracy. To reduce system overhead, however, you should use the maximum value appropriate for your application.
定时器的分辨力,毫秒。小的数值表示高的分辨力;分辨力为0表示周期事件应该以允许的最高精度发生。尽管如此为减小系统开销,你应该使用适合你应用的最大值。
lpTimeProc
回调函数。
dwUser
User-supplied callback data. 用户提供的回调函数数据
fuEvent
Timer event type. This parameter may include one of the following values.
定时事件类型。这个参数可能包含以下值的一个:
TIME_ONESHOT Event occurs once, after uDelay milliseconds.事件在uDelay毫秒后发生一次
TIME_PERIODIC Event occurs every uDelay milliseconds.事件每隔uDelay毫秒发生一次
Example:
在类CTimerCallbackDlg中
protected:
virtual void OnMMTimer();//声明要回调的成员方法
//作为回调函数的静态方法
static void CALLBACK TimerCallBack(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
CTimerCallbackDlg * pThis=(CTimerCallbackDlg*)dwUser;//由this指针获得实例的指针
pThis->OnMMTimer();//调用要回调的成员方法
}
/***********************************/
//一个定时器的使能禁能按钮
void CTimerCallbackDlg::OnTimerEn()
{
// TODO: Add your control notification handler code here
if(!m_en)
{
//返回定时器的id,用于停止定时器,回调静态函数,传入this指针
m_timerId=timeSetEvent(100,100,&TimerCallBack,(DWORD)this,1);
m_en=true;
SetDlgItemText(IDC_TimerEn,"Stop");
}
else
{
//关闭定时器
timeKillEvent(m_timerId);
m_en=false;
SetDlgItemText(IDC_TimerEn,"Start");
}
}
常见需求
1 获取时间及其时间间隔。
CTime curTime = CTime::GetCurrentTime() ;//获取当前的时间并保存到curTime
int nYear = curTime.GetYear() ;
int nMonth = curTime.GetMonth() ;
int nDay = curTime.GetDay() ;
int nHour = curTime.GetHour() ;
int nMin = curTime.GetMinute() ;
int nSec = curTime.GetSecond() ;
//计算时间差
CTimeSpan timeSpan ;
timeSpan = curTime - startTime ;
cout << "两时时间差" << endl ;
cout<<timeSpan.GetDays()<<"天"
<<timeSpan.GetHours()<<"小时"
<<timeSpan.GetMinutes()<<"分"
<<timeSpan.GetSeconds()<<"秒" <<endl ;
常见问题
一.线程切换时间
1. windows中多线程切换调度时间为20ms,所以低于20ms的精度用多线程很难做。
2. windows自带定时器,说是能精确到1ms,但实际硬件是用的Intel8259定时器芯片来产生硬件中断08H。中断08H每隔54.925 ms产生一次,所以定时器在Windows中的最大缺点是
计时器的最大分辨率是55ms,低于55ms的精度要求不要用。
3.Sleep()函数由于释放CPU控制权,故CPU占有率很小,但他的优先级很低,所以他的定时时间不准,而且相差会很大,要等其他调用和函数结束后才能返回。windows98下在精度
小于50ms,Windows2000,XP小于20ms的时候不要用。
注释,标题用的5号字。