在嵌入式编程中中,经常需要输出系统的当前时间、计算程序的执行时间、使用计时器等。最近也做了不少关于时间的操作,今天就认真总结一下,部分内容是在网上看到的。自己经过验证总结出来。
(time_t在time.h中定义:typedef long int time_t)time_t记录自1970年1月1日凌晨以来的秒数,在Linux/Unix上定义为long int类型,在32位系统上,time_t最多只能记录2,147,483,647秒,也就是说到了2038年将会产生溢出(这就是为什么很多嵌入式设备日期只能够设置到2038年的原因),但在64位系统上不会出现此问题。函数double difftime(time_t time1, time_t time0);用于比较两个time_t类型的值。
#include <time.h> void main() { long lSeconds = 0; lSeconds = time(NULL); printf("seconds = %ld\n", lSeconds); }
-----------------------------------------------------------------
tm_sec | 秒,范围是0~59。
tm_min | 分,范围是0~59。
tm_hour | 时,范围是0~23。
tm_mday | 日,范围是1~31。
tm_mon | 月,范围是0~11,注意是0到11。
tm_year | 年,自1900以来的年数。
tm_wday | 星期几,从星期天开始计算,范围是0~6。
tm_yday | 一年中的哪一天,0~365。
tm_isdst | 夏令时间(DST)的一个标志。 -----------------------------------------------------------------
函数介绍:
struct tm *gmtime(const time_t *timep)
函数功能 : 将日历时间转化为格林威治标准时间,并保存在tm结构
参数:日历时间的返回值
struct tm* localtime(const time_t *timep)
函数功能:将日历时间转化为本地时间,并保存至tm结构
参数:日历时间的返回值。
例:
#include <stdio.h> #include <time.h> int main(void) { struct tm *local; time_t t; t = time(null); //获取日历时间 local = localtime(&t);//将日历时间转化为本地时间,并保存在struct tm结构中 printf("local hour is :%d\n",local->tm_hour); local = gmtime(&t); //将日历时间转化为格林威治时间,并保存在struct tm结构中 printf("utc hour is :%d\n",local->tm_hour); return 0; }
利用函数gmtime()、localtime()可以将日历时间转化为格林威治时间和本地时间,虽然用户可通过结构体tm来获取这些时间值,但看起来还不方便,最好是将所有的信息,如年、月、日、星期、时、分、秒以字符串的形式显示出来。
char *asctime(const struct tm *tm)
函数功能:将tm格式的时间转化为字符串
参数:日历时间的返回值
例如: SAT Jul 30 08:43:03 2005
该函数必须按照下面3个步骤来进行.
<1>使用函数time()来获取日历时间
<2>使用函数gmtime()将日历时间转化为格林威治标准时间
<3>使用函数asctime()将tm格式的时间转化为字符串
例:
#include <time.h> #include <stdio.h> int main(void) { struct tm *ptr; time_t lt; lt = time(null); //获取日历时间 ptr = gmtime(<); //转化为格林威治时间*/ printf(asctime(ptr)); //以格林威治时间的字符串方式打印 printf(ctime(<)); //以本地时间的字符串方式打印*/ return 0; }
char *ctime(const time_t *timep)
函数功能:将日历时间转化为本地时间的字符串形式
参数:日历时间的返回值。
该函数.必须按照下面2个步骤来进行.
<1>使用函数time()来获取日历时间
<2>使用函数ctime()将日历时间直接转化为字符串
PS:有time函数将time_t值转换为struct tm类型值,函数mktime 可以将struct
tm类型值转换为time_t类型的值,其原型为:
time_t mktime(struct tm *tm);
函数用法:可以在做某件事情之前调用gettimeofday(),在做完该件事情之后调用gettimeofday(),两个函数的参数1的差就是做该事情所消耗的时间。也经常在程序中作为定时器处理,比如每隔多长时间时间执行一次什么事件。
struct timeval
{
int tv_sec; //秒数
int tv_usec; //微秒数
}
// 计算时间差,单位毫秒 int elapsed_time(struct timeval *ct, struct timeval *lt) { int elapsed = (ct->tv_sec - lt->tv_sec) * 1000 + (ct->tv_usec - lt->tv_usec) / 1000; return elapsed; }
这里要介绍两个函数,同time和gettimeofday对应,stime和settimeofday,原型如下:
int stime(time_t *t);
int settimeofday(const struct timeval *tv, const struct timezone *tz);
只是settimeofday设置的时间比stime更精确罢了。
(1)unsigned int sleep(unsigned int seconds)
函数功能 : 使程序睡眠seconds秒
参数 : 需要休眠的秒数
(2)void usleep(unsigned long usec)
函数功能 : 使程序睡眠usec微秒
参数 : 需要休眠的秒数
#include <stdio.h> #include <unistd.h> #include <signal.h> void alarm_handler(int signum) { rintf("Five seconds passed!\n"); } void func(void) { signal(SIGALRM, alarm_handler); alarm(5); pause(); } int main(void) { func(); return 0; }
程序将在5秒之后执行alarm_handler函数,这里还使用了pause函数,用于挂起进程直到捕捉到一个信号时才退出。注意alarm一次只能发送发送一个信号,如果要再次发送信号,需要重新调用alarm函数。
除了alarm外,还可以使用setitimer来设置定时器,使用getitimer来获取定时器的状态,原型如下:
int setitimer(int which, const struct itimerval *restrict value, struct itimerval *restrict ovalue);
int getitimer(int which, struct itimerval *value);
说明:
需要包含头文件sys/time.h
which参数有三种取值:
ITIMER_REAL 按实际时间记时,时间到了之后发送SIGALRM信号,相当于alarm。
ITIMER_VIRTUAL 仅当进程执行时才进行记时,发送SIGVTALRM信号。
ITIMER_PROF 当进程执行时和系统执行该进程时都记时,发送的是SIGPROF信号。
struct itimerval用来指定定时时间,定义如下:
在setitimer函数中,ovalue如果不为空,则保留上次调用设置的值。
gmtime() 函数将日历时间timep转换为用UTC时间表示的时间。它可能返回NULL,比如年份不能放到一个整数中。返回值指向一个静态分配的结构,该结构可能会被接下来的任何日期和时间函数调用覆盖。gmtime_r()函数功能与此相同,但是它可以将数据存储到用户提供的结构体中。
localtime() 函数将日历时间timep转换为用户指定的时区的时间。这个函数的行为好像是它调用了tzset(3) 并且将外部变量tzname设置为当前时区的信息,将timezone设为UTC和本地标准时间的差值,并且,如果在一年的部分时间使用日光节约规则时将daylight设置为非空值。返回值指向一个静态分配的结构,该结构可能会被接下来的任何日期和时间函数调用覆盖。localtime_r()函数功能与此相同,但是它可以将数据存储到用户提供的结构体中。它不需要设置tzname。
例1:
#include <stdio.h> #include <time.h> int main() { time_t cur_time = time(NULL); if (cur_time < 0) { perror("time"); return -1; } struct tm utc_tm; if (NULL == gmtime_r(&cur_time, &utc_tm)) { perror("gmtime"); return -1; } struct tm local_tm; if (NULL == localtime_r(&cur_time, &local_tm)) { perror("localtime" ); return -1; } printf("UTC = %s", asctime(&utc_tm)); printf("LOC = %s", asctime(&local_tm)); printf("LOC = %s", ctime(&cur_time)); return 0; }输出结果:
xzg@byxc-PDSML:~/test$ gcc -o time time.c
xzg@byxc-PDSML:~/test$ ./time
UTC = Tue Jul 15 01:41:08 2014
LOC = Tue Jul 15 09:41:08 2014
LOC = Tue Jul 15 09:41:08 2014
系统时间使用了UTC,可以看到“本地时间=
UTC时间 + 8”,输出正确。
例2:
#include <stdio.h> #include <time.h> int main() { time_t cur_time = time(NULL); if (cur_time < 0) { perror("time"); return -1; } struct tm *utc_tm = gmtime( &cur_time ); if( NULL == utc_tm ) { perror("gmtime" ); return -1; } <strong>printf("UTC = %s", asctime(utc_tm) );</strong> struct tm *local_tm = localtime( &cur_time ); if( NULL == local_tm ) { perror("localtime" ); return -1; } printf("LOC = %s", asctime(local_tm) ); printf("LOC = %s", ctime(&cur_time) ); return 0; }输出结果:
xzg@byxc-PDSML:~/test$ gcc -o time1 time1.c
xzg@byxc-PDSML:~/test$ ./time1
UTC = Tue Jul 15 02:00:38 2014
LOC = Tue Jul 15 10:00:38 2014
LOC = Tue Jul 15 10:00:38 2014
xzg@byxc-PDSML:~/test$
例3:
#include <stdio.h> #include <time.h> int main() { time_t cur_time = time(NULL); if (cur_time < 0) { perror("time"); return -1; } struct tm *utc_tm = gmtime( &cur_time ); if( NULL == utc_tm ) { perror("gmtime" ); return -1; } struct tm *local_tm = localtime( &cur_time ); if( NULL == local_tm ) { perror("localtime" ); return -1; } <strong>printf("UTC = %s", asctime(utc_tm) );</strong> printf("LOC = %s", asctime(local_tm) ); printf("LOC = %s", ctime(&cur_time) ); return 0; }输出结果:
xzg@byxc-PDSML:~/test$ gcc -o time1 time1.c
xzg@byxc-PDSML:~/test$ ./time1
UTC = Tue Jul 15 10:03:26 2014
LOC = Tue Jul 15 10:03:26 2014
LOC = Tue Jul 15 10:03:26 2014
这程序输出有错,UTC时间和本地时间相同了“可能会被接下来的任何日期和时间函数调用覆盖”造成的。
总结:
使用gmtime和localtime后要立即处理结果,否则返回的指针指向的内容可能会被覆盖,一个好的方法是使用gmtime_r和localtime_r,由于使用了用户分配的内存,这两个函数是不会出错的。
原文:http://blog.csdn.net/sin0803/article/details/37767865