C语言中如何获取时间?精度如何? 1 使用time_t time( time_t * timer ) 精确到秒 2 使用clock_t clock() 获得的是CPU时间精确到1/CLOCKS_PER_SEC秒 3 计算时间差使用double difftime( time_t timer1,time_t timer0 ) 4 使用DWORD GetTickCount() 精确到毫秒 5 若是使用MFC的CTime类,能够用CTime::GetCurrentTime() 精确到秒 6 要获取高精度时间,可使用 BOOLQueryPerformanceFrequency(LARGE_INTEGER lpFrequency) 获取系统的计数器的频率 BOOLQueryPerformanceCounter(LARGE_INTEGER lpPerformanceCount) 获取计数器的值 而后用两次计数器的差除以Frequency就获得时间。 7 Multimedia Timer Functions The following functions areused with multimedia timers. timeBeginPeriod/timeEndPeriod/timeGetDevCaps/timeGetSystemTime //******************************************************************* //用标准C实现获取当前系统时间的函数程序员
一.time()函数算法
#include -- 必须的时间函数头文件 time_t -- 时间类型(time.h 定义是typedef long time_t; 追根溯源,time_t是long) struct tm -- 时间结构,time.h 定义以下: int tm_sec; int tm_min; int tm_hour; int tm_mday; int tm_mon; int tm_year; int tm_wday; int tm_yday; int tm_isdst; time ( &rawtime ); -- 获取时间,以秒计,从1970年1月一日起算,存于rawtime localtime ( &rawtime ); -- 转为当地时间,tm 时间结构 asctime ()-- 转为标准ASCII时间格式: 星期 月 日 时:分:秒 年编程
三.gettime(&t); 听说tc2.0的time结构含有毫秒信息 #include #include int main(void) { struct time t; gettime(&t); printf("The current timeis: -:d:d.d\n", t.ti_hour, t.ti_min, t.ti_sec,t.ti_hund); return 0; } time 是一个结构体,, 其中成员函数 ti_hund 是毫秒。。。windows
//Unix ##unix时间相关,也是标准库的 //**** 1.timegm函数只是将struct tm结构转成time_t结构,不使用时区信息; time_t timegm(struct tm tm); 2.mktime使用时区信息 time_t mktime(struct tm tm); timelocal 函数是GNU扩展的与posix函数mktime至关 time_t timelocal (struct tmtm); 3.gmtime函数只是将time_t结构转成struct tm结构,不使用时区信息; struct tm * gmtime(const time_tclock); 4.localtime使用时区信息 struct tm * localtime(consttime_t clock); 1.time获取时间,stime设置时间 time_t t; t = time(&t); 2.stime其参数应该是GMT时间,根据本地时区设置为本地时间; int stime(time_t tp) 3.UTC=true 表示采用夏时制; 4.文件的修改时间等信息所有采用GMT时间存放,不一样的系统在获得修改时间后经过localtime转换成本地时间; 5.设置时区推荐使用setup来设置; 6.设置时区也能够先更变/etc/sysconfig/clock中的设置再将ln -fs/usr/share/zoneinfo/xxxx/xxx /etc/localtime 才能重效 time_t只能表示68年的范围,即mktime只能返回1970-2038这一段范围的time_t 看看你的系统是否有time_t64,它能表示更大的时间范围 //windows ##Window里面的一些不同的 //****函数
一.CTime () 类 VC编程通常使用CTime类 得到当前日期和时间布局
CTime t = GetCurrentTime(); SYSTEMTIME 结构包含毫秒信息 typedef struct _SYSTEMTIME { WORD wYear; WORD wMonth; WORD wDayOfWeek; WORD wDay; WORD wHour; WORD wMinute; WORD wSecond; WORD wMilliseconds; } SYSTEMTIME, *PSYSTEMTIME; SYSTEMTIME t1; GetSystemTime(&t1) CTime curTime(t1); WORD ms = t1.wMilliseconds; SYSTEMTIME sysTm; ::GetLocalTime(&sysTm); 在time.h中的_strtime() //只能在windows中用 char t[11]; _strtime(t); puts(t);性能
//***************************** 得到当前日期和时间 CTimetm=CTime::GetCurrentTime(); CStringstr=tm.Format("%Y-%m-%d"); 在VC中,咱们能够借助CTime时间类,获取系统当前日期,具体使用方法以下: CTime t =CTime::GetCurrentTime(); //获取系统日期,存储在t里面 int d=t.GetDay(); //得到当前日期 int y=t.GetYear(); //获取当前年份 int m=t.GetMonth(); //获取当前月份 int h=t.GetHour(); //获取当前为几时 int mm=t.GetMinute(); //获取当前分钟 int s=t.GetSecond(); //获取当前秒 int w=t.GetDayOfWeek(); //获取星期几,注意1为星期天,7为星期六测试
二.CTimeSpan类 若是想计算两段时间的差值,可使用CTimeSpan类,具体使用方法以下: CTime t1( 1999, 3, 19, 22, 15,0 ); CTime t =CTime::GetCurrentTime(); CTimeSpan span=t-t1; //计算当前系统时间与时间t1的间隔 int iDay=span.GetDays(); //获取这段时间间隔共有多少天 int iHour=span.GetTotalHours();//获取总共有多少小时 intiMin=span.GetTotalMinutes();//获取总共有多少分钟 intiSec=span.GetTotalSeconds();//获取总共有多少秒spa
三._timeb()函数 _timeb定义在SYS\TIMEB.H,有四个fields dstflag millitm time timezone void _ftime( struct _timeb*timeptr ); struct _timeb timebuffer; _ftime( &timebuffer ); 取当前时间:文档讲能够到ms,有人测试,好象只能到16ms!.net
##如何设定当前系统时间---------------------------------------windows SYSTEMTIMEm_myLocalTime,*lpSystemTime; m_myLocalTime.wYear=2003; m_myLocalTime.wM; m_myLocalTime.wDay=1; m_myLocalTime.wHour=0; m_myLocalTime.wMinute=0; m_myLocalTime.wSec; m_myLocalTime.wMillisec; lpSystemTime=&m_myLocalTime; if( SetLocalTime(lpSystemTime)) //此处换成 SetSystemTime( )也不行 MessageBox("OK !"); else MessageBox("Error!"); SYSTEMTIMEm_myLocalTime,*lpSystemTime; m_myLocalTime.wYear=2003; m_myLocalTime.wM; m_myLocalTime.wDay=1; lpSystemTime=&m_myLocalTime; if( SetDate(lpSystemTime) ) //此处换成 SetSystemTime( )也不行 MessageBox("OK !"); else MessageBox("Error!");
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/khuang2008/archive/2008/12/09/3483274.aspx
一种制做微秒级精度定时器的方法 当使用定时器时,在不少状况下只用到毫秒级的时间间隔,因此只需用到下面的两种经常使用方式就知足要求了。一是用SetTimer函数创建一个定时器后,在程序中经过处理由定时器发送到线程消息队列中的WM_TIMER消息,而获得定时的效果(退出程序时别忘了调用和SetTimer配对使用的KillTimer函数)。二是利用GetTickCount函数能够返回自计算机启动后的时间,经过两次调用GetTickCount函数,而后控制它们的差值来取得定时效果,此方式跟第一种方式同样,精度也是毫秒级的。 用这两种方式取得的定时效果虽然在许多场合已经知足实际的要求,但因为它们的精度只有毫秒级的,并且在要求定时时间间隔小时,实际定时偏差大。下面介绍一种能取得高精度定时的方法。 在一些计算机硬件系统中,包含有高精度运行计数器(high-resolution performancecounter),利用它能够得到高精度定时间隔,其精度与CPU的时钟频率有关。采用这种方法的步骤以下: 一、首先调用QueryPerformanceFrequency函数取得高精度运行计数器的频率f。单位是每秒多少次(n/s),此数通常很大。 二、在须要定时的代码的两端分别调用QueryPerformanceCounter以取得高精度运行计数器的数值n1,n2。两次数值的差值经过f换算成时间间隔,t=(n2-n1)/f。 下面举一个例子来演示这种方法的使用及它的精确度。 在VC 6.0 下用MFC创建一个对话框工程,取名为HightTimer.在对话框面板中控件的布局以下图: 其中包含两个静态文本框,两个编辑框和两个按纽。上面和下面位置的编辑框的ID分别为IDC_E_TEST和IDC_E_ACTUAL,经过MFC ClassWizard添加的成员变量也分别对应为DWORD m_dwTest和DWORD m_dwAct. “退出”按纽的ID为IDOK,“开始测试”按纽ID为IDC_B_TEST,用MFC ClassWizard添加此按纽的单击消息处理函数以下: void CHightTimerDlg::OnBTest() { // TODO: Add your controlnotification handler code here UpdateData(TRUE); //取输入的测试时间值到与编辑框相关联的成员变量m_dwTest中
LARGE_INTEGER frequence; if(!QueryPerformanceFrequency(&frequence)) //取高精度运行计数器的频率,若硬件不支持则返回FALSE MessageBox("Your computerhardware doesn't support the high-resolution performance counter", "Not Support",MB_ICONEXCLAMATION | MB_OK);
LARGE_INTEGER test, ret; test.QuadPart = frequence.QuadPart* m_dwTest / 1000000; //经过频率换算微秒数到对应的数量(与CPU时钟有关),1秒=1000000微秒 ret = MySleep( test ); //调用此函数开始延时,返回实际花销的数量
m_dwAct = (DWORD)(1000000 *ret.QuadPart / frequence.QuadPart ); //换算到微秒数
UpdateData(FALSE); //显示到对话框面板 } 其中上面调用的MySleep函数以下:
LARGE_INTEGERCHightTimerDlg::MySleep(LARGE_INTEGER Interval) ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // 功能:执行实际的延时功能 // 参数:Interval 参数为须要执行的延时与时间有关的数量 // 返回值:返回此函数执行后实际所用的时间有关的数量 /////////////////////////////////////////////////////////////////////////////////////////////////////////// { LARGE_INTEGER privious,current, Elapse;
QueryPerformanceCounter(&privious ); current = privious;
while( current.QuadPart -privious.QuadPart < Interval.QuadPart ) QueryPerformanceCounter( ¤t );
Elapse.QuadPart =current.QuadPart - privious.QuadPart;
return Elapse; } 注:别忘了在头文件中为此函数添加函数声明。
至此,能够编译和执行此工程了,结果如上图所示。在本人所用的机上(奔腾366, 64M内存)测试,当测试时间超过3微秒时,准确度已经很是高了,此时机器执行自己延时函数代码的时间对须要延时的时间影响很小了。
上面的函数因为演示测试的须要,没有在函数级封装,下面给出的函数基本上能够以全局函数的形式照搬到别的程序中。
BOOL MySleep(DWORD dwInterval) ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // 功能:执行微秒级的延时功能 // 参数:Interval 参数为须要的延时数(单位:微秒) // 返回值:若计算机硬件不支持此功能,返回FALSE,若函数执行成功,返回TRUE /////////////////////////////////////////////////////////////////////////////////////////////////////////// { BOOL bNormal = TRUE; LARGE_INTEGER frequence,privious, current, interval;
if(!QueryPerformanceFrequency(&frequence)) { ::MessageBox(NULL, "Yourcomputer hardware doesn't support the high-resolution performancecounter", "Not Support",MB_ICONEXCLAMATION | MB_OK); //或其它的提示信息 return FALSE; }
interval.QuadPart =frequence.QuadPart * dwInterval / 1000000;
bNormal = bNormal &&QueryPerformanceCounter( &privious ); current = privious;
while( current.QuadPart -privious.QuadPart < interval.QuadPart ) bNormal = bNormal &&QueryPerformanceCounter( ¤t );
return bNormal; }
须要指出的是,因为在此函数中的代码不少,机器在执行这些代码所花费的时间也很长,因此在须要几个微秒的延时时,会影响精度。实际上,读者在熟悉这种方法后,只要使用QueryPerformanceFrequency和QueryPerformanceCounter这两个函数就能按实际须要写出本身的延时代码了。
使用CPU时间戳进行高精度计时 对关注性能的程序开发人员而言,一个好的计时部件既是益友,也是良师。计时器既能够做为程序组件帮助程序员精确的控制程序进程,又是一件有力的调试武器,在有经验的程序员手里能够尽快的肯定程序的性能瓶颈,或者对不一样的算法做出有说服力的性能比较。
在Windows平台下,经常使用的计时器有两种,一种是timeGetTime多媒体计时器,它能够提供毫秒级的计时。但这个精度对不少应用场合而言仍是太粗糙了。另外一种是QueryPerformanceCount计数器,随系统的不一样能够提供微秒级的计数。对于实时图形处理、多媒体数据流处理、或者实时系统构造的程序员,善用QueryPerformanceCount/QueryPerformanceFrequency是一项基本功。
本文要介绍的,是另外一种直接利用Pentium CPU内部时间戳进行计时的高精度计时手段。如下讨论主要得益于《Windows图形编程》一书,第15页-17页,有兴趣的读者能够直接参考该书。关于RDTSC指令的详细讨论,能够参考Intel产品手册。本文仅仅做抛砖之用。
在Intel Pentium以上级别的CPU中,有一个称为“时间戳(Time Stamp)”的部件,它以64位无符号整型数的格式,记录了自CPU上电以来所通过的时钟周期数。因为目前的CPU主频都很是高,所以这个部件能够达到纳秒级的计时精度。这个精确性是上述两种方法所没法比拟的。
在Pentium以上的CPU中,提供了一条机器指令RDTSC(ReadTime Stamp Counter)来读取这个时间戳的数字,并将其保存在EDX:EAX寄存器对中。因为EDX:EAX寄存器对刚好是Win32平台下C++语言保存函数返回值的寄存器,因此咱们能够把这条指令当作是一个普通的函数调用。像这样:
inline unsigned __int64GetCycleCount() { __asm RDTSC }
可是不行,由于RDTSC不被C++的内嵌汇编器直接支持,因此咱们要用_emit伪指令直接嵌入该指令的机器码形式0X0F、0X31,以下:
inline unsigned __int64GetCycleCount() { __asm _emit 0x0F __asm _emit 0x31 }
之后在须要计数器的场合,能够像使用普通的Win32 API同样,调用两次GetCycleCount函数,比较两个返回值的差,像这样:
unsigned long t; t = (unsigned long)GetCycleCount(); //Do Something time-intensive ... t -= (unsigned long)GetCycleCount();
《Windows图形编程》第15页编写了一个类,把这个计数器封装起来。有兴趣的读者能够去参考那个类的代码。做者为了更精确的定时,作了一点小小的改进,把执行RDTSC指令的时间,经过连续两次调用GetCycleCount函数计算出来并保存了起来,之后每次计时结束后,都从实际获得的计数中减掉这一小段时间,以获得更准确的计时数字。但我我的以为这一点点改进意义不大。在个人机器上实测,这条指令大概花掉了几十到100多个周期,在Celeron 800MHz的机器上,这不过是十分之一微秒的时间。对大多数应用来讲,这点时间彻底能够忽略不计;而对那些确实要精确到纳秒数量级的应用来讲,这个补偿也过于粗糙了。
这个方法的优势是:
1.高精度。能够直接达到纳秒级的计时精度(在1GHz的CPU上每一个时钟周期就是一纳秒),这是其余计时方法所难以企及的。
2.成本低。timeGetTime 函数须要连接多媒体库winmm.lib,QueryPerformance* 函数根据MSDN的说明,须要硬件的支持(虽然我尚未见过不支持的机器)和KERNEL库的支持,因此两者都只能在Windows平台下使用(关于DOS平台下的高精度计时问题,能够参考《图形程序开发人员指南》,里面有关于控制定时器8253的详细说明)。但RDTSC指令是一条CPU指令,凡是i386平台下Pentium以上的机器均支持,甚至没有平台的限制(我相信i386版本UNIX和Linux下这个方法一样适用,但没有条件试验),并且函数调用的开销是最小的。
3.具备和CPU主频直接对应的速率关系。一个计数至关于1/(CPU主频Hz数)秒,这样只要知道了CPU的主频,能够直接计算出时间。这和QueryPerformanceCount不一样,后者须要经过QueryPerformanceFrequency获取当前计数器每秒的计数次数才能换算成时间。
这个方法的缺点是:
1.现有的C/C++编译器多数不直接支持使用RDTSC指令,须要用直接嵌入机器码的方式编程,比较麻烦。
2.数据抖动比较厉害。其实对任何计量手段而言,精度和稳定性永远是一对矛盾。若是用低精度的timeGetTime来计时,基本上每次计时的结果都是相同的;而RDTSC指令每次结果都不同,常常有几百甚至上千的差距。这是这种方法高精度自己固有的矛盾。
关于这个方法计时的最大长度,咱们能够简单的用下列公式计算:
自CPU上电以来的秒数 = RDTSC读出的周期数 / CPU主频速率(Hz)
64位无符号整数所能表达的最大数字是1.8×10^19,在个人Celeron 800上能够计时大约700年(书中说能够在200MHz的Pentium上计时117年,这个数字不知道是怎么得出来的,与个人计算有出入)。不管如何,咱们大可没必要关心溢出的问题。
下面是几个小例子,简要比较了三种计时方法的用法与精度
//Timer1.cpp 使用了RDTSC指令的Timer类//KTimer类的定义能够参见《Windows图形编程》P15 //编译行:CL Timer1.cpp /link USER32.lib #include <stdio.h> #include "KTimer.h" main() { unsigned t; KTimer timer; timer.Start(); Sleep(1000); t = timer.Stop(); printf("Lasting Time: %d\n",t); }
//Timer2.cpp 使用了timeGetTime函数 //需包含<mmsys.h>,但因为Windows头文件错综复杂的关系 //简单包含<windows.h>比较偷懒:) //编译行:CL timer2.cpp /link winmm.lib #include <windows.h> #include <stdio.h>
main() { DWORD t1, t2; t1 = timeGetTime(); Sleep(1000); t2 = timeGetTime(); printf("Begin Time: %u\n", t1); printf("End Time: %u\n", t2); printf("Lasting Time: %u\n",(t2-t1)); }
//Timer3.cpp 使用了QueryPerformanceCounter函数 //编译行:CL timer3.cpp /linkKERNEl32.lib #include <windows.h> #include <stdio.h>
main() { LARGE_INTEGER t1, t2, tc; QueryPerformanceFrequency(&tc); printf("Frequency: %u\n", tc.QuadPart); QueryPerformanceCounter(&t1); Sleep(1000); QueryPerformanceCounter(&t2); printf("Begin Time: %u\n", t1.QuadPart); printf("End Time: %u\n", t2.QuadPart); printf("Lasting Time: %u\n",( t2.QuadPart- t1.QuadPart)); }
//////////////////////////////////////////////// //以上三个示例程序都是测试1秒钟休眠所耗费的时间 file://测/试环境:Celeron 800MHz / 256M SDRAM // Windows 2000 Professional SP2 // Microsoft Visual C++ 6.0 SP5 ////////////////////////////////////////////////
如下是Timer1的运行结果,使用的是高精度的RDTSC指令 Lasting Time: 804586872
如下是Timer2的运行结果,使用的是最粗糙的timeGetTime API Begin Time: 20254254 End Time: 20255255 Lasting Time: 1001
如下是Timer3的运行结果,使用的是QueryPerformanceCount API Frequency: 3579545 Begin Time: 3804729124 End Time: 3808298836 Lasting Time: 3569712