c语言获取时间

<script type="text/javascript"> </script> <script type="text/javascript"> </script>

C 语言获取系统时间的几种方式

 

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 要获取高精度时间,可以使用

BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency)

获取系统的计数器的频率

BOOL QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount)

获取计数器的值

然后用两次计数器的差除以 Frequency 就得到时间。

7 Multimedia Timer Functions

The following functions are used with multimedia timers.

timeBeginPeriod/timeEndPeriod/timeGetDevCaps/timeGetSystemTime

//*********************************************************************

// 用标准 C 实现获取当前系统时间的函数

 

.time() 函数

 

     time(&rawtime) 函数获取当前时间距 1970 1 1 日的秒数,以秒计数单位,存于 rawtime 中。

#include "time.h"

void main ()

{

time_t rawtime;

struct tm * timeinfo;

time ( &rawtime );

timeinfo = localtime ( &rawtime );

printf ( "/007The current date/time is: %s", asctime (timeinfo) );

exit(0);

}

=================

#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 时间格式:

星期 时:分:秒

 

-----------------------------------------------------------------------------

.clock() 函数 , clock() 函数,得到系统启动以后的毫秒级时间,然后除以 CLOCKS_PER_SEC ,就可以换成“秒”,标准 c 函数。

clock_t clock ( void );

#include

clock_t t = clock();

long sec = t / CLOCKS_PER_SEC;

他是记录时钟周期的,实现看来不会很精确,需要试验验证;

---------------------------------------------------------------------------

.gettime(&t); 据说 tc2.0 time 结构含有毫秒信息

#include

#include

int main(void)

{

struct time t;

gettime(&t);

printf("The current time is: %2d:%02d:%02d.%02d/n",

t.ti_hour, t.ti_min, t.ti_sec, t.ti_hund);

return 0;

}

time 是一个结构体,, 其中成员函数 ti_hund 是毫秒。。。

 

--------------------------------------------------------------------------------

.GetTickCount(), 这个是 windows 里面常用来计算程序运行时间的函数;

DWORD dwStart = GetTickCount();

// 这里运行你的程序代码

DWORD dwEnd = GetTickCount();

(dwEnd-dwStart) 就是你的程序运行时间 , 以毫秒为单位

这个函数只精确到 55ms 1 tick 就是 55ms

--------------------------------------------------------------------------------

.timeGetTime()t,imeGetTime() 基本等于 GetTickCount() ,但是精度更高

DWORD dwStart = timeGetTime();

// 这里运行你的程序代码

DWORD dwEnd = timeGetTime();

(dwEnd-dwStart) 就是你的程序运行时间 , 以毫秒为单位

虽然返回的值单位应该是 ms, 但传说精度只有 10ms

=========================================

//*****************************************************************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 tm *tm);

3.gmtime 函数只是将 time_t 结构转成 struct tm 结构 , 不使用时区信息 ;

struct tm * gmtime(const time_t *clock);

4.localtime 使用时区信息

struct tm * localtime(const time_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);

 

//*****************************

获得当前日期和时间

CTime tm=CTime::GetCurrentTime();

CString str=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(); // 获取总共有多少小时

int iMin=span.GetTotalMinutes();// 获取总共有多少分钟

int iSec=span.GetTotalSeconds();// 获取总共有多少秒

 

 

------------------------------------------------------------------------------

 

._timeb() 函数

_timeb 定义在 SYS/TIMEB.H ,有四个 fields

dstflag

millitm

time

timezone

void _ftime( struct _timeb *timeptr );

struct _timeb timebuffer;

_ftime( &timebuffer );

取当前时间 : 文档讲可以到 ms, 有人测试 , 好象只能到 16ms!

 

 

. 设置计时器

定义 TIMER ID

#define TIMERID_JISUANFANGSHI 2

在适当的地方设置时钟 , 需要开始其作用的地方 ;

SetTimer(TIMERID_JISUANFANGSHI,200,NULL);

在不需要定时器的时候的时候销毁掉时钟

KillTimer(TIMERID_JISUANFANGSHI);

对应 VC 程序的消息映射

void CJisuan::OnTimer(UINT nIDEvent)

{switch(nIDEvent)}

---------------------------------------------------------------------------------------

## 如何设定当前系统时间 ---------------------------------------windows

SYSTEMTIME m_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 !");

SYSTEMTIME m_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   performance   counter ),利用它可以获得高精度定时间隔,其精度与 CPU 的时钟频率有关。采用这种方法的步骤如下:

1 首先调用 QueryPerformanceFrequency 函数取得高精度运行计数器的频率 f 。单位是每秒多少次( n/s ),此数一般很大。

2 在需要定时的代码的两端分别调用 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   control   notification   handler   code   here

  UpdateData(TRUE);   // 取输入的测试时间值到与编辑框相关联的成员变量 m_dwTest

   

  LARGE_INTEGER   frequence;

  if(!QueryPerformanceFrequency(   &frequence))   // 取高精度运行计数器的频率,若硬件不支持则返回 FALSE

  MessageBox("Your   computer   hardware   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_INTEGER   CHightTimerDlg::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,   "Your   computer   hardware   doesn't   support   the   high-resolution   performance   counter",

  "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 Read   Time   Stamp   Counter )来读取这个时间戳的数字,并将其保存在 EDX:EAX 寄存器对中。由于 EDX:EAX 寄存器对恰好是 Win32 平台下 C++ 语言保存函数返回值的寄存器,所以我们可以把这条指令看成是一个普通的函数调用。像这样:

 

inline   unsigned   __int64   GetCycleCount()  

  {  

__asm   RDTSC  

  }  

 

但是不行,因为 RDTSC 不被 C++ 的内嵌汇编器直接支持,所以我们要用 _emit 伪指令直接嵌入该指令的机器码形式 0X0F 0X31 ,如下:

 

inline   unsigned   __int64   GetCycleCount()  
  {  
    __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   /link   KERNEl32.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   
  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值