在软件设计中经常会用到关于时间的处理,用来计算语句、函数的执行时间,这时就需要精确到毫秒甚至是微妙的时间。我们首先来介绍一下,时间单位:

时间单位还有:秒(s)、毫秒(ms)、微秒 (μs)、纳秒(ns)、皮秒(ps)、飞秒(fs)、阿秒、渺秒     
1 s = 10^3 ms = 10^6 us = 10^9 ns = 10^12 ps = 10^15 fs=10^18阿秒=10^21渺秒=10^43普朗克常数


一、首先介绍几个时间函数,

查看:man ctime

NAME  asctime,  ctime,  gmtime, localtime, mktime, asctime_r, ctime_r, gmtime_r, localtime_r - transform date and time to broken-down time  or ASCII  SYNOPSIS  #include <time.h>  char *asctime(const struct tm *tm);  char *asctime_r(const struct tm *tm, char *buf);  char *ctime(const time_t *timep);  char *ctime_r(const time_t *timep, char *buf);  struct tm *gmtime(const time_t *timep);  struct tm *gmtime_r(const time_t *timep, struct tm *result);  struct tm *localtime(const time_t *timep);  struct tm *localtime_r(const time_t *timep, struct tm *result);  time_t mktime(struct tm *tm);  Feature Test Macro Requirements for glibc (see feature_test_macros(7)):  asctime_r(), ctime_r(), gmtime_r(), localtime_r():  _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _BSD_SOURCE || _SVID_SOURCE || _POSIX_SOURCE  DESCRIPTION  The ctime(), gmtime() and localtime() functions all take an argument of data type  time_t  which  represents  calendar  time.   When  interpreted as an absolute time value, it represents the number of seconds elapsed since the Epoch, 1970-01-01 00:00:00 +0000 (UTC).  The  asctime()  and  mktime() functions both take an argument representing broken-down time which is a representation separated into  year, month, day, etc.  Broken-down time is stored in the structure tm which is defined in <time.h> as follows:  struct tm {  int tm_sec;         /* seconds */  int tm_min;         /* minutes */  int tm_hour;        /* hours */  int tm_mday;        /* day of the month */  int tm_mon;         /* month */  int tm_year;        /* year */  int tm_wday;        /* day of the week */  int tm_yday;        /* day in the year */  int tm_isdst;       /* daylight saving time */  };  

ctime函数:可以把time函数得到的结果转换成一个时间字符串

gmtime函数:可以把time函数得到的结果按照格林尼治时间转换成一个结构体

localtime函数:可以把time函数得到的结果按照当前时区转换成一个结构体

asctime函数:可以把一个记录时间的结构体转换成字符串,一般与上两个函数合用的

格林时间,与北京时间换算,参看:TIMEBIE

/* 时间函数演示 */
#include <stdio.h>
#include <time.h>
int main()
{  time_t tm = 0;//long int别名 //time(0)是一个long int空地址  time (&tm);  printf ("%s\n", ctime (&tm));  struct tm *p_tm = gmtime (&tm);  printf ("%s\n", asctime (p_tm));  struct tm *p_tm1 = localtime (&tm); //声明语句  printf ("%s\n", asctime (p_tm1));  return 0;
}
输出结果:
Sat Jan 14 14:48:10 2017  Sat Jan 14 06:48:10 2017  Sat Jan 14 14:48:10 2017  


二、Linux 获取时间戳

第一种方法:微秒级时间戳

查看:man gettimeofday

功能:获取/设置时间

NAME  gettimeofday, settimeofday - get / set time  SYNOPSIS  #include <sys/time.h>  int gettimeofday(struct timeval *tv, struct timezone *tz);  int settimeofday(const struct timeval *tv, const struct timezone *tz);  Feature Test Macro Requirements for glibc (see feature_test_macros(7)):  settimeofday(): _BSD_SOURCE  DESCRIPTION  The functions gettimeofday() and settimeofday() can get and set the time as well as a timezone.  The tv argument is a struct timeval  (as specified in <sys/time.h>):  struct timeval {  time_t      tv_sec;     /* seconds */  suseconds_t tv_usec;    /* microseconds */  };  and gives the number of seconds and microseconds since the Epoch (see time(2)).  The tz argument is a struct timezone:  struct timezone {  int tz_minuteswest;     /* minutes west of Greenwich */  int tz_dsttime;         /* type of DST correction */  };  If either tv or tz is NULL, the corresponding structure is not set or returned.  

下面是个简单的例子,用来统计程序的执行时间:

#include <stdio.h>
#include <sys/time.h>    int main(void)
{    struct timeval start,end;    gettimeofday( &start, NULL );  /*测试起始时间*/    usleep (10000); //使用 usleep  gettimeofday( &end, NULL );   /*测试终止时间*/    int timeuse = (end.tv_usec - start.tv_usec);    printf("运行时间为:%d us\n",timeuse);    return 0;    }
输出结果:
10193 us  

第二种方法:毫秒级时间戳,微秒级精度不够
查看:man ftime
功能:返回的日期和时间
NAMEftime - return date and timeSYNOPSIS#include <sys/timeb.h>int ftime(struct timeb *tp);DESCRIPTIONThis  function  returns  the current time as seconds and milliseconds since the Epoch, 1970-01-01 00:00:00 +0000 (UTC).  The time isreturned in tp, which is declared as follows:struct timeb {time_t         time;unsigned short millitm;short          timezone;short          dstflag;};Here time is the number of seconds since the Epoch, and millitm is the number of milliseconds since time seconds  since  the  Epoch.The  timezone  field  is  the local timezone measured in minutes of time west of Greenwich (with a negative value indicating minuteseast of Greenwich).  The dstflag field is a flag that, if nonzero, indicates that Daylight Saving time applies  locally  during  theappropriate part of the year.POSIX.1-2001 says that the contents of the timezone and dstflag fields are unspecified; avoid relying on them.RETURN VALUEThis function always returns 0.  (POSIX.1-2001 specifies, and some systems document, a -1 error return.)

tp结构定义:
struct timeb{
  time_t time; /* 为1970-01-01至今的秒数*/
  unsigned short millitm; /* 千分之一秒即毫秒 */
  short timezonel; /* 为目前时区和Greenwich相差的时间,单位为分钟 */
  short dstflag; /* 为日光节约时间的修正状态,如果为非0代表启用日光节约时间修正 */
};

下面是个简单的例子:
#include <stdio.h>
#include <sys/timeb.h>  long long getSystemTime() {  struct timeb t;  ftime(&t);  return (1000 * t.time + t.millitm) * 1000;
}  int main() {  long long start = getSystemTime();  usleep(3000);  long long end = getSystemTime();  printf("time: %lld us\n", end-start);  return 0;
}
输出结果:
3000 us

第三种方法:秒级时间戳
查看:man difftime    
功能:返回两个time_t型变量之间的时间间隔,即 计算两个时刻之间的时间差。
NAMEdifftime - calculate time differenceSYNOPSIS#include <time.h>double difftime(time_t time1, time_t time0);DESCRIPTIONThe  difftime()  function returns the number of seconds elapsed between time time1 and time time0, represented as a double.  Each ofthe times is specified in calendar time, which means its value is a measurement (in  seconds)  relative  to  the  Epoch,  1970-01-0100:00:00 +0000 (UTC).
下面是个简单的例子:
#include <stdio.h>
#include <time.h>  int main(){  time_t t_start, t_end;  t_start = time(NULL) ;  sleep(3);  t_end = time(NULL) ;  printf("time: %.0f s\n", difftime(t_end,t_start)) ;  return 0;
}
输出结果:
time: 3 s


第四种方法:C/C++中的计时函数clock()
在MSDN中,查得对clock函数定义如下:
clock_t clock(void) ;
简单而言,就是该程序从启动到函数调用占用CPU的时间。这个函数返回从“开启这个程序进程”到“程序中调用clock()函数”时之间的CPU时钟计时单元(clock tick)数,在MSDN中称之为挂钟时间(wal-clock);若挂钟时间不可取,则返回-1。其中clock_t是用来保存时间的数据类型
在time.h文件中,我们可以找到对它的定义:
#ifndef _CLOCK_T_DEFINED
typedef long clock_t;
#define _CLOCK_T_DEFINED
#endif
很明显,clock_t是一个长整形数。在time.h文件中,还定义了一个常量CLOCKS_PER_SEC它用来表示一秒钟会有多少个时钟计时单元,其定义如下:
#define CLOCKS_PER_SEC ((clock_t)1000)
在linux系统下,CLOCKS_PER_SEC的值可能有所不同,目前使用的linux打印出来的值是1000000,表示的是微秒。这一点需要注意。
可以看到每过千分之一秒(1毫秒),调用clock()函数返回的值就加1。下面举个例子,你可以使用公式clock()/CLOCKS_PER_SEC来计算一个进程自身的运行时间:
void elapsed_time()
{
printf("Elapsed time:%u secs.\n",clock()/CLOCKS_PER_SEC);
}

当然,你也可以用clock函数来计算你的机器运行一个循环或者处理其它事件到底花了多少时间:

#include"time.h"
#include"stdlib.h"
#include"stdio.h"  void sleep (clock_t wait);  int main (void)
{  long    i = 600000000L;  clock_t start, finish;  double  duration;  printf( "延时3秒\n" );  sleep( (clock_t)3 * CLOCKS_PER_SEC );  printf( "Done!\n" );  start = clock();  printf("程序启动,start = %ld\n", start);  while( i-- )  ;  finish = clock();  printf("循环结束,finish = %ld\n", finish);  duration = (double)(finish - start) / CLOCKS_PER_SEC;  printf( "CPU 占用的总时间: %2.1f seconds\n", duration );  printf("程序退出...\n");return 0;
}  void sleep( clock_t wait )
{  clock_t goal;  goal = wait + clock();  while( goal > clock() )  ;
}
输出结果:
延时3秒
Done!
程序启动,start = 3000000
循环结束,finish = 4810000
CPU 占用的总时间: 1.8 seconds
程序退出...

它的另一个功能:利用clock()函数和for循环完成程序定时暂停
#include <stdio.h>
#include<time.h>
int main(void)
{int b = 0, i = 0;b=clock()/CLOCKS_PER_SEC;for(i=0;i<10;)//完成100秒定时{i = i-b;i = clock()/CLOCKS_PER_SEC;}printf ("finish\n");return 0;
}
输出结果:
time ./a.out
finishreal  0m10.171s
user    0m2.180s
sys 0m7.820s


第五种方法:使用time 命令
最简单的方法了,上面的例子其实已经用到。在执行可执行文件的时候,使用如下命令,便可以统计该程序的运行时间。
time ./a.out
real    0m10.171s
user    0m2.180s
sys 0m7.820s

time命令,统计的结果包涵程序加载和退出的时间,统计的结果比较粗糙。若想得出函数运行时间较为准确的结果,建议使用上面的几种方法。
三、定时器:

查看:man getitimer

NAME  getitimer, setitimer - get or set value of an interval timer  SYNOPSIS  #include <sys/time.h>  int getitimer(int which, struct itimerval *curr_value);  int setitimer(int which, const struct itimerval *new_value,  struct itimerval *old_value);  DESCRIPTION  The system provides each process with three interval timers, each decrementing in a distinct time domain.  When any timer expires, a  signal is sent to the process, and the timer (potentially) restarts.  ITIMER_REAL    decrements in real time, and delivers SIGALRM upon expiration.  ITIMER_VIRTUAL decrements only when the process is executing, and delivers SIGVTALRM upon expiration.  ITIMER_PROF    decrements both when the process executes and when the system is executing on behalf of the  process.   Coupled  with  ITIMER_VIRTUAL,  this  timer  is  usually used to profile the time spent by the application in user and kernel space.  SIGPROF is delivered upon expiration.  Timer values are defined by the following structures:  struct itimerval {  struct timeval it_interval; /* next value */  struct timeval it_value;    /* current value */  };
The function getitimer() fills the structure pointed to by curr_value with the current setting for the timer specified by which (one  of  ITIMER_REAL, ITIMER_VIRTUAL, or ITIMER_PROF).  The element it_value is set to the amount of time remaining on the timer, or zero  if the timer is disabled.  Similarly, it_interval is set to the reset value.  The function setitimer() sets the specified timer to the value in new_value.  If old_value is non-NULL, the old value of  the  timer  is stored there.  Timers decrement from it_value to zero, generate a signal, and reset to it_interval.  A timer which is set to zero (it_value is zero  or the timer expires and it_interval is zero) stops.  Both tv_sec and tv_usec are significant in determining the duration of a timer.  Timers will never expire before the requested time, but may expire some (short) time afterward, which depends on  the  system  timer  resolution  and  on  the system load; see time(7).  (But see BUGS below.)  Upon expiration, a signal will be generated and the timer  reset.  If the timer expires while the process is active (always true for ITIMER_VIRTUAL) the signal will be  delivered  immediately  when generated.  Otherwise the delivery will be offset by a small time dependent on the system loading.  RETURN VALUE  On success, zero is returned.  On error, -1 is returned, and errno is set appropriately.  

第一个参数:计时器的类型
ITIMER_REAL--真实计时器,主要描述进程运行的真实时间,通过产生SIGALRM信号工作(掌握)
ITIMER_VIRTUAL 虚拟计时器,主要描述进程在用户空间消耗的时间,通过产生SIGVTALRM信号工作(了解)
ITIMER_PROF--实用计时器,主要描述进程在用户空间和内核空间共同消耗的时间,通过产生SIGPROF信号工作(了解)
第二个参数:计时器的新值
struct itimerval 
{
struct timeval it_interval; /* next value */    //间隔时间
struct timeval it_value;    /* current value */ //启动时间
};
struct timeval 
{
long tv_sec;   /* seconds */       //秒数
long tv_usec;  /* microseconds */  //微秒
};
第三个参数:用于获取计时器的旧值,不想带直接给NULL
函数功能:主要用于用户获取/设置计时器的数值

下面是个简单的例子:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/time.h>void fa(int signo)
{printf("贪吃蛇移动了一步\n");
}int main()
{struct itimerval t_start, t_end;getitimer (ITIMER_REAL, &t_start);printf("Start time: %ld us\n", t_start.it_value.tv_usec);//设置SIGALRM进行自定义处理signal(SIGALRM,fa);struct itimerval timer;//设置启动时间timer.it_value.tv_sec=0;//秒数timer.it_value.tv_usec=30000;//微秒//设置间隔时间timer.it_interval.tv_sec=1;timer.it_interval.tv_usec=0;//设置真实计时器开始工作int res=setitimer(ITIMER_REAL,&timer,NULL);if(-1==res){perror("settimer"),exit(-1);}getitimer (ITIMER_REAL, &t_end);printf("End time: %ld us\n", t_end.it_value.tv_usec);long cost_time = t_end.it_value.tv_usec - t_start.it_value.tv_usec;printf("Cost time: %ld us\n", cost_time);while (1);return 0;
}
输出结果:
Start time: 0 us
End time: 29997 us
Cost time: 29997 us
贪吃蛇移动了一步
贪吃蛇移动了一步
贪吃蛇移动了一步
贪吃蛇移动了一步
贪吃蛇移动了一步
^C


扩展:

1、预定义宏里有 __TIME__

__TIME__源文件编译时间,格式为“hh: mm: ss”

#include <stdio.h>
int main (void)
{   printf ("The time is %s\n", __TIME__);  return 0;
}
输出结果:
The time is 18:24:24

2、头文件 time.h
日期和时间函数: 本类别给出时间和日期处理函数
----------------------------------------

下面的函数感兴趣的可以自行百度
时间操作函数得到处理器时间 clock
得到时间差difftime
设置时间mktime
得到时间time
时间转换函数 得到以ASCII码表示的时间asctime
得到字符串表示的时间ctime
得到指定格式的时间strftime

__BEGIN_NAMESPACE_STD
/* Time used by the program so far (user time + system time).The result / CLOCKS_PER_SECOND is program time in seconds.  */
extern clock_t clock (void) __THROW;/* Return the current time and put it in *TIMER if TIMER is not NULL.  */
extern time_t time (time_t *__timer) __THROW;/* Return the difference between TIME1 and TIME0.  */
extern double difftime (time_t __time1, time_t __time0)__THROW __attribute__ ((__const__));/* Return the `time_t' representation of TP and normalize TP.  */
extern time_t mktime (struct tm *__tp) __THROW;/* Format TP into S according to FORMAT.Write no more than MAXSIZE characters and return the numberof characters written, or 0 if it would exceed MAXSIZE.  */
extern size_t strftime (char *__restrict __s, size_t __maxsize,__const char *__restrict __format,__const struct tm *__restrict __tp) __THROW;
__END_NAMESPACE_STD

3、根据文件时间戳的相关属性来查找文件

参看:C语言再学习 -- Linux下find命令用法

我们可以使用 stat 命令来查看一个文件的时间信息,如下:

root@zslf-virtual-machine:/mnt/test# stat ./  文件:"./"  大小:4096       块:8          IO 块:4096   目录
设备:801h/2049d   Inode:291601      硬链接:2
权限:(0755/drwxr-xr-x)  Uid:( 1000/    zslf)   Gid:( 1000/    zslf)
最近访问:2016-11-25 09:45:24.699140785 +0800
最近更改:2016-11-25 09:45:22.255140690 +0800
最近改动:2016-11-25 09:45:22.255140690 +0800
创建时间:-  

-atime、-mtime、-ctime、-amin、-mmin、-cmin

这里的 -atime、-mtime、-ctime 分别对应的是 “最近一次访问时间”,“最近一次内容修改时间”,“最近一次属性修改时间”,这里的atime的单位指的是“天”,amin 的单位是分钟。


参看:Linux之atime,mtime,ctime

文件的 Access time,atime:是在读取文件或者执行文件时更改的。
文件的 Modified time,mtime: 是在写入文件时随文件内容的更改而更改的。
文件的 Create time,ctime :是在写入文件、更改所有者、权限或链接设置时随 Inode 的内容更改而更改的。 


文件各种事件标记的显示方法

ls -lc filename         列出文件的 ctime 
ls -lu filename         列出文件的 atime 
ls -l filename          列出文件的 mtime

查看:man ls

-c     with  -lt:  sort  by,  and show, ctime (time of last modification of file status information) with -l: show ctime and sort byname otherwise: sort by ctime, newest first-u     with -lt: sort by, and show, access time with -l: show access time and sort by name otherwise: sort by access time-l     use a long listing format
查找在五天内没有访问过的文件
root@zslfe:/mnt/test# find ./ -atime +5  
查找在五天内访问过的文件
root@zslf:/mnt/test# find ./ -atime -5
./
./f.sh
./g.sh
./a.sh
./c.sh
./b.sh 

4、UNIX时间戳

参看:Linux命令date日期时间和Unix时间戳互转
工具:Unix时间戳转换工具
(1)将日期转换为Unix时间戳
将当前时间以Unix时间戳表示:
# date +%s
1492565563

(2)转换指定日期为Unix时间戳:

# date -d '2013-2-22 22:14' +%s
1361542440

(3)将Unix时间戳转换为日期时间
不指定日期时间的格式:

# date -d @1361542596
Fri Feb 22 22:16:36 CST 2013

(4)指定日期格式的转换:

# date -d @1361542596 +"%Y-%m-%d %H:%M:%S"
2013-02-22 22:16:36

C语言再学习 -- 时间函数相关推荐

  1. C语言再学习 -- 随机数函数

    参看:C++中随机函数rand()和srand()的用法 rand ()函数:可以用来获得一个随机数 所在头文件: stdlib.h 函数说明 : rand()的内部实现是用线性同余法做的,它不是真的 ...

  2. C语言再学习 -- 字符串和字符串函数

    最近身体很不给力,很乏累!白天没精神,晚上睡不着,心情还很烦躁.看书都有点看不下去的样子,到了C语言最难掌握的部分了,数组.指针.字符串.硬着头皮看书总结吧. 一.字符串 1.字符串介绍 字符串是以空 ...

  3. C语言再学习 -- 关键字return和exit ()函数

    终于到了最后一个关键字 return 了.感觉时间过的飞快,转眼间又是一年,如果时间可以 return 就好了. 一.return 介绍 参看:C语言中return 用法 1.含义: return 表 ...

  4. C语言再学习 -- 再论数组和指针

    之前有总结指针数组,但是现在看来总结的太简单了.好多重要的知识点都是一带而过的.本想在后面添加后来想想算了,还是再写一篇文章来详细介绍数组和指针这对冤家吧. 之前总结的,参看:C语言再学习 -- 数组 ...

  5. C语言再学习 -- 关键字const

    const 关键字其实我们并不陌生,之前有讲过const修饰数组和指针.现在来详细介绍这个关键字. 参看:[C/C++和指针]著名的<const的思考> 一.const 介绍 1.cons ...

  6. C语言再学习 -- 存储类型关键字

    定义: 是对声明的实现或者实例化.连接器(linker)需要它(定义)来引用内存实体.与上面的声明相应的定义如下:参看:C语言再学习 -- 存储类.链接 C语言中有 5 个作为存储类说明符的关键字,分 ...

  7. C语言再学习 -- 结构和其他数据形式

    一.结构体 结构体可以用来创建新的数据类型,这种数据类型可以把多个其他类型合并成一个整体,采用结构体声明的变量叫做结构变量,结构体需要先声明然后才能使用,声明结构体需要使用struct关键字,结构体声 ...

  8. C语言再学习 -- C 预处理器

    gcc/cc xxx.c  可以编译链接C源程序生成一个可执行文件 a.out 整个过程中可以划分为以下的4步流程: (1)预处理/预编译: 主要用于包含头文件的扩展,以及执行宏替换等 //加上 -E ...

  9. C语言再学习 -- 存储类、链接

    这一章是我看的时间最长的一章了,表面上是有很多关键字和几个函数需要学习,其实我知道是自己最近不在状态了,做项目没进展,看书看不下去,两头都放不下,最后两头都没有做好.不由的想起一句话,你不快乐是因为: ...

最新文章

  1. Asp.net 的网络打印 – Javascript 控制打印
  2. 普通用户下变成-bash-3.2$的解决方法
  3. Bitcoin.com| 比特币现金2019·年度回顾
  4. B02_NumPy数据属性(ndarray.ndim,ndarray.shape,ndarray.itemsize,ndarray.flags)
  5. 【FPGA Verilog】实验二:key按键基础实验
  6. mysql 1055 解决方案_MySQL报错1055解决方案 - 树懒学堂
  7. linux的poll_wait函数,select() 与 poll()两个函数接口的作用
  8. Java程序员从笨鸟到菜鸟之(八十七)跟我学jquery(三)jquery动态创建元素和常用函数示例...
  9. 车牌识别sdk android,Android车牌识别sdk
  10. mysql msdtc 不支持_如何解决服务器上的msdtc不可用问题
  11. 华为安全HCIP-Security H12-721、H12-722、H12-723题库,含三套vce软件
  12. 51单片机LCD1602程序详解
  13. 分享常见的视频加密算法原理及其优缺点
  14. PPT之如何设置一个箭头围绕一个顶点旋转?
  15. [创业-18]:财务报表之资产负债表
  16. leelen可视对讲怎么接线_电子门铃怎么安装 电子对讲门铃安装方法【详细介绍】...
  17. 香港伦敦金交易平台排行榜(2022最新版)
  18. CSDN 下载 版块问题解决日志
  19. 北京某高端养老机构开业3年 : 1次失信,2场官司,3项处罚,处在高危中的养老行业如何应对多维度经营风险?
  20. 从制造中来到智造中去

热门文章

  1. Selenium简介以及selenium环境搭建
  2. 将Jquery序列化后的表单值转换成Json
  3. 算法编程题的心得体会
  4. [Java,MVC] Eclipse下搭建Spring MVC
  5. Go web 编程资源
  6. cuda core和sp
  7. Python系统调用——运行其他程序
  8. 无功功率控制模式matlab,第9章_MATLAB在风力发电技术中的应用仿真.ppt
  9. 计算天数java_Java,计算两个日期之间的天数
  10. 科大星云诗社动态20210212