Linux 下的时间编程总结

在嵌入式编程中中,经常需要输出系统的当前时间、计算程序的执行时间、使用计时器等。最近也做了不少关于时间的操作,今天就认真总结一下,部分内容是在网上看到的。自己经过验证总结出来。

1、时间的类型

1.格林威治标准时间

coordinated universal time(UTC)是世界标准时间,即常说的格林威治标准时间(greenwich mean time,GMT)。

2.日历时间

日历时间(calendar time)是用"一个标准时间点(如1970年1月1日0点)到此时经过的秒数"来表示的时间。

2、常用时间函数的API

1、获取日历时间

   #include <time.h>

time_t time(time_t *tloc)

函数功能 : 获取日历时间,即从1970年1月1日0点到现在所经历的秒数.

参数 : 通常设置为NULL

 (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);
}

2、将日历时间转换为格林威治标准时间和本地时间

通常用户得到日历时间的秒数后可以将这些秒数转化为更容易接受的时间表示方式,这些表示时间的方式有格林威治时间、本地时间等首先介绍一个表示时间常用的数据结构。

struct tm

{

int tm_sec;   //秒值

int tm_min;   //分钟值

int tm_hour;  //小时值

int tm_mday;  //本月第几日

int tm_mon;   //本年第几月

int tm_year;  //tm_year+1900=哪一年

int tm_wday;  //本周第几日

int tm_yday;  //本年第几日

int tm_isdst; //日光节约时间

}

-----------------------------------------------------------------
 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;
}

3、时间显示

利用函数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);

4、计算事件耗时

int gettimeofday(struct timeval *tv, struct timezone *tz)

函数功能 : 获取从今日凌晨(0:0:0)到现在的时间差,常用于计算事件耗时

参数1 : 存放从今日凌晨(0:0:0)到现在的时间差,时间差以秒或微秒为单位,以结构体形式存放

参数2 : 常设置为null

函数用法:可以在做某件事情之前调用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;
}

5、设置系统时钟

这里要介绍两个函数,同time和gettimeofday对应,stime和settimeofday,原型如下:

int stime(time_t *t);
int settimeofday(const struct timeval *tv, const struct timezone *tz);

只是settimeofday设置的时间比stime更精确罢了。

6、延时函数

(1)unsigned int sleep(unsigned int seconds)

函数功能 : 使程序睡眠seconds秒

参数 : 需要休眠的秒数

(2)void usleep(unsigned long usec)

函数功能 : 使程序睡眠usec微秒

参数 : 需要休眠的秒数

7、定时器

unsigned alarm(unsigned seconds);

#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用来指定定时时间,定义如下:

struct itimerval

{

struct timerval it_interval;
/* next value */

struct timerval it_value;
/* current value */

};

在setitimer函数中,ovalue如果不为空,则保留上次调用设置的值。

3、时间函数的安全用法

在写代码的时候,经常会用到读取系统时间的函数。localtime函数不是线程安全的。如果在多线程里调用localtime函数,很可能会出现问题。

多线程应用里面,应该用localtime_r函数替代localtime函数,因为localtime_r是线程安全的。同样gmtime函数和gmtime_r函数

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);

gmtime() 函数将日历时间timep转换为用UTC时间表示的时间。它可能返回NULL,比如年份不能放到一个整数中。返回值指向一个静态分配的结构,该结构可能会被接下来的任何日期和时间函数调用覆盖。gmtime_r()函数功能与此相同,但是它可以将数据存储到用户提供的结构体中。

localtime() 函数将日历时间timep转换为用户指定的时区的时间。这个函数的行为好像是它调用了tzset(3) 并且将外部变量tzname设置为当前时区的信息,将timezone设为UTC和本地标准时间的差值,并且,如果在一年的部分时间使用日光节约规则时将daylight设置为非空值。返回值指向一个静态分配的结构,该结构可能会被接下来的任何日期和时间函数调用覆盖。localtime_r()函数功能与此相同,但是它可以将数据存储到用户提供的结构体中。它不需要设置tzname。

4、时间函数功能测试

例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;
}

输出结果:

[email protected]:~/test$ gcc -o time time.c

[email protected]:~/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;
}

输出结果:

[email protected]:~/test$ gcc -o time1 time1.c

[email protected]:~/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

[email protected]:~/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;
}

输出结果:

[email protected]:~/test$ gcc -o time1 time1.c

[email protected]:~/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,由于使用了用户分配的内存,这两个函数是不会出错的。

Linux 下的时间编程总结

时间: 2024-08-06 20:07:25

Linux 下的时间编程总结的相关文章

linux下的bash编程简要学习

linux下的bash编程简要学习     1.bash是什么: linux运行时系统只会运行系统运行所需要的运行脚本即系统守护进程,一般根据用户自己需求设定和实现的服务需要手动启动,这种服务进程通常由bash启动,脚本中的命令通常被按照一定规则被bash读取视作参数,因此在脚本头部要申明运行的bash类型,bash命令分为内建命令及外部命令,外部命令通过PATH进行依次查找. bash读取命令后将其启动(fork)成为一个进程,依次启动服务     2.bash控制语句:         本地

linux下的时钟编程

1.时钟相关的API函数原型 #include <unistd.h> unsigned int sleep(unsigned int seconds); unsigned int alarm(unsigned int seconds); int usleep(useconds_t usec); #include <sys/time.h> int getitimer(int which, struct itimerval *curr_value); int setitimer(int

Linux下的C编程实战

Linux下的C编程实战(一) ――开发平台搭建 1.引言 Linux操作系统在服务器领域的应用和普及已经有较长的历史,这源于它的开源特点以及其超越Windows的安全性和稳定性.而近年来, Linux操作系统在嵌入式系统领域的延伸也可谓是如日中天,许多版本的嵌入式Linux系统被开发出来,如ucLinux.RTLinux.ARM-Linux等等. 在嵌入式操作系统方面,Linux的地位是不容怀疑的,它开源.它包含TCP/IP协议栈.它易集成GUI. 鉴于Linux操作系统在服务器和嵌入式系统领

浅析 Linux 中的时间编程和实现原理一—— Linux 应用层的时间编程【转】

本文转载自:http://www.cnblogs.com/qingchen1984/p/7007631.html 本篇文章主要介绍了"浅析 Linux 中的时间编程和实现原理一—— Linux 应用层的时间编程",主要涉及到浅析 Linux 中的时间编程和实现原理一—— Linux 应用层的时间编程方面的内容,对于浅析 Linux 中的时间编程和实现原理一—— Linux 应用层的时间编程感兴趣的同学可以参考一下. 简介: 本文试图完整地描述 Linux 系统中 C 语言编程中的时间问

Linux下C++的编程——开偏介绍

C++是一个功能强大而又应用广泛的计算机语言,就应用领域而言,几乎无所不在,因为有操作系统的地方就会有C++的存在,热门程序而言,也就仅次于C和Java.而C与C++又有天然的血缘关系. 从事C++开发近两年,虽然开发的产品都是跨平台的,但个人直接接触到的编程工程还是更偏重于Windows平台(至少开发环境更多的是在Windows平台,还写过"带你玩转Visual Studio"系列的博文),而现在要自己独立地带领一个项目的开发,还是一个跨平台的项目,也就有必要到Linux下C++的编

Linux下C++的编程——开发环境搭建与第一个程序

上一篇文章Linux下C++的编程--开偏介绍中我们已经介绍了GUN.GCC.G++等一些重要的概念,现在应该开始动手实践了! 开发工具的安装 环境 Distributions版本:CentOS 6.7 Linux内核片:2.6.32-573.3.1.el6.i686 一般Linux安装完之后默认就已经安装了GCC(GNU Compiler Collection),你可以查看一下gcc和g++的版本号检查gcc和g++是否已经安装. [luowf@luoweifu ~]$ gcc -v gcc

LINUX下C语言编程基础

实验二 Linux下C语言编程基础 一.实验目的 1. 熟悉Linux系统下的开发环境 2. 熟悉vi的基本操作 3. 熟悉gcc编译器的基本原理 4. 熟练使用gcc编译器的常用选项 5 .熟练使用gdb调试技术 6. 熟悉makefile基本原理及语法规范 7. 掌握静态库和动态库的生成 二.实验步骤 1. 快捷键 Ubuntu中: 2. vim VIM是一个非常好的文本编辑器,很多专业程序员使用VIM编辑代码,即使以后你不编写程序,只要跟文本打交道,都应该学学VIM,可以浏览参考一下普通人

linux应用开发-时间编程

linux应用开发-时间编程 一 时间类型 世界标准时间:格林威治时间 日历时间:从1970-1-1起的秒数 二 时间函数 1 获取日历时间 函数名 time 函数原形 time_t time(time_t *t) 函数功能 从1970年1月1日的时间,单位为秒 所属头文件 #include<time.h> 返回值 成功返回时间的秒速 失败返回-1 参数说明 保存返回值 2 获取格林威治时间 函数名 gmtime 函数原形 struct tm *gmtime(const time_t *tim

Linux下C++的编程——GDB进行程序调试

GDB简介 我们在Linux下C++的编程--开偏介绍一文中已经简单介绍了GDB的功能,是类Unix系统的主要调试工具,可进行断点调试,跟踪程序,动态改变执行环境等功能. 从一个程序开始调试 下面我们就从一个程序开始讲解一下GDB的简单用法.假设我们有如下的程序: GDBTest1.cpp #include <iostream> int Accumulation(int n) { int result = 0; for(int i = 0; i < n; i ++) { result +