在软件设计中经常会用到关于时间的处理,用来计算语句、函数的执行时间,这时就需要精确到毫秒甚至是微妙的时间。我们首先来介绍一下,时间单位:
时间单位还有:秒(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
NAME
ftime - return date and time
SYNOPSIS
#include <sys/timeb.h>
int ftime(struct timeb *tp);
DESCRIPTION
This function returns the current time as seconds and milliseconds since the Epoch, 1970-01-01 00:00:00 +0000 (UTC). The time is
returned 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 minutes
east of Greenwich). The dstflag field is a flag that, if nonzero, indicates that Daylight Saving time applies locally during the
appropriate part of the year.
POSIX.1-2001 says that the contents of the timezone and dstflag fields are unspecified; avoid relying on them.
RETURN VALUE
This 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
NAME
difftime - calculate time difference
SYNOPSIS
#include <time.h>
double difftime(time_t time1, time_t time0);
DESCRIPTION
The difftime() function returns the number of seconds elapsed between time time1 and time time0, represented as a double. Each of
the times is specified in calendar time, which means its value is a measurement (in seconds) relative to the Epoch, 1970-01-01
00: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
clock_t clock(void) ;
简单而言,就是该程序从启动到函数调用占用CPU的时间。这个函数返回从“开启这个程序进程”到“程序中调用clock()函数”时之间的CPU时钟计时单元(clock tick)数,在MSDN中称之为挂钟时间(wal-clock);若挂钟时间不可取,则返回-1。其中clock_t是用来保存时间的数据类型。
#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)
可以看到每过千分之一秒(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
程序退出...
#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
finish
real 0m10.171s
user 0m2.180s
sys 0m7.820s
time ./a.out
real 0m10.171s
user 0m2.180s
sys 0m7.820s
查看: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 number
of 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、根据文件时间戳的相关属性来查找文件
我们可以使用 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 的单位是分钟。
文件的 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 by
name 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时间戳
将当前时间以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