您的位置:首页 > 运维架构 > Linux

linux编程中与时间相关的问题总结

2016-03-22 00:25 609 查看

一、与时间相关的概念

GMT:Greenwich Mean Time,格林尼治平均时。格林尼治标准时间是19世纪中叶大英帝国的基准时间,同时也是事实上的世界基准时间。

UTC:Universal Time Coordinated,环球通用协调时间。基本上UTC的本质强调的是比GMT更为精确的世界时间标准,在不需要精确到秒的情况通常也将GMT和UTC视作等同。

DST:Daylight Saving Time,指在夏天太阳升起的比较早时,将时钟拨快一小时以提早日光的使用;

CST:CST可以同时表示美国UT-6:00,澳大利亚UT+9:30,中国UT+8:00,古巴UT-4:00四个国家的标准时间;

Epoch:时间轴上特定的一个时间点,定义为从格林威治时间1970年01月01日00时00分00秒。记为1970年1月1日00:00:00 UTC。

UNIX时间戳:英文表示为Unix timestamp、Unix time或者POSIX time。是从Epoch开始所经过的秒数,不考虑闰秒。在大多数的UNIX系统中UNIX时间戳存储为32位,这样会引发2038年问题或Y2038。

Calendar Time:表示的意义同UNIX时间戳。

Broken-down Time:使用tm结构存储的时间,tm 数据结构将时间分别保存到代表年,月,日,时,分,秒等不同的变量中,不再是一个令人费解的64位整数。tm数据结构是各种自定义格式转换函数所需要的输入形式。

Real-Time:也称wall-clock,即我们人类自然感受的时间。

Virtual-Time:进程执行所占用的cpu时间(即站在进程的角度看时间),如果在过去的一秒钟指定进程没有被调用,则virtual time为0s,real time为1s。

Prof-Time:系统在用户态和内核态所占用cpu时间的总和;

clock tick:时钟滴答,当PIT通道0的计数器减到0值时,它就在IRQ0上产生一次时钟中断,即一次时钟滴答。

jiffies:记录着从电脑开机到现在总共的”时钟中断”的次数。启动时内核将该变量初始化为0,此后每次时钟中断处理程序都会增加该变量的值。jiffies类型为无符号长整型(unsigned long),其他任何类型存放它都不正确。

xtime:从cmos电路或rtc芯片中取得的时间,一般是从某一历史时刻开始到现在的时间;

二、相关函数汇总

函数名函数用途
time(…)获取日历时间存储在time_t结构之中,分辨率为秒。
stime(…)设置系统时间。
gettimeofday(…)同time(…),但是分辨率达到微妙级别,一般用于计算程序运行所耗费的时间。
settimeofday(…)同stime(…),只是设置更精确的时间更精确罢了。
clock_gettime(…)同time(…),但是分辨率为纳秒级,还能根据时钟的类型获取不同的时间。
gmtime(…)将time_t类型的UTC时间转换成struct tm类型的UTC时间。
localtime(…)将time_t类型的本地时间转换成struct tm类型的本地时间。
mktime(…)将struct tm类型值转换为time_t类型的值。
ctime(…)将time_t类型的时间转换成固定格式的字符串形式,返回的字符串是静态分配的。
asctime(…)将struct tm格式的时间转化为固定格式的字符串形式,返回的字符串是静态分配的。
strftime(…)将tm格式的时间转化为字符串,显示格式可以自定义
sleep(…)使程序睡眠seconds秒
usleep(…)使程序睡眠usec微秒
difftime(…)计算出两个日历时间差,大致实现为
#define difftime(t1,t0) (double)(t1 - t0)
alarm()设置单次定时器,超时发送SIGALRM信号。
setitimer()可以设置三种循环定时器,超时分别发送不同的信号。
getitimer()对应setitimer的查询。
注:

time()和gettimeofday()调用比较占用系统资源,所以不如对时间精度要求不高的情况下,尽量减少调用次数;

三、经典配图回顾

刚开始学习linux的时候没看明白下面的时间转换图,现在再看看豁然开朗



四、相关数据结构

time_t:在Linux/Unix上定义为long int类型,在32位系统上,time_t最多只能记录2,147,483,647秒,也就是说到了2038年将会产生溢出,但在64位系统上不会出现此问题。

struct tm:为了更好的理解time_t表示的时间,于是产生了tm结构

struct tm {
int tm_sec;  /* Seconds (0-60) */
int tm_min;    /* Minutes (0-59) */
int tm_hour;  /* Hours (0-23) */
int tm_mday;  /* Day of the month (1-31) */
int tm_mon;   /* Month (0-11) */
int tm_year;  /* Year since 1900 */
int tm_wday;  /* Day of the week (Sunday = 0)*/
int tm_yday;  /* Day in the year (0-365; 1 Jan = 0)*/
int tm_isdst; /* Daylight saving time flag
> 0: DST is in effect;
= 0: DST is not effect;
< 0: DST information not available */
};


struct timeval:上面两个都是表示时间点,而这个结构体表示时间段。

struct timeval {
time_t      tv_sec;    /* seconds */
suseconds_t tv_usec;    /* microseconds */
};


struct itimerval:设置间隔定时器时使用的结构体。

struct itimerval {
struct timeval it_interval; /* 从第二次开始以后的超时时间 */
struct timeval it_value; /* 第一次超时时间 */
};


五、linux环境下的时间戳转换

在LINUX系统中,有许多场合都使用时间戳的方式表示时间,即从1970年1月1日起至当前的天数或秒数。

分别以标准格式和时间戳来显示当前时间

[root@365linux ~]# date
2010年 08月 10日 星期二 03:39:21 CST
[root@365linux ~]# date +%s
1281382775


显示指定时间的时间戳

[root@365linux ~]# date -d "2010-07-20 10:25:30" +%s
1279592730


将时间戳转换为标准时间格式

方法1:使用date命令

[root@localhost tmp]#  date -d "@1279592730"
Tue Jul 20 10:25:30 CST 2010
[root@localhost tmp]#  date -d "@1279592730" +"%Y%m%d %H:%M:%S"
20100720 10:25:30
[root@localhost tmp]#  date -d "@1279592730" +"%F %H:%M:%S"
2010-07-20 10:25:30
[root@localhost tmp]# date -d "1970-01-01 utc 1279592730 seconds"
Tue Jul 20 10:25:30 CST 2010
[root@localhost tmp]# date -d "1970-01-01 utc 1279592730 seconds" +"%F %H:%M:%S"
2010-07-20 10:25:30


方法2:使用awk里的时间函数

[root@365linux ~]# echo "1279592730" |awk '{print strftime ("%F %T",$0)}'
2010-07-20 10:25:30


方法3:使用perl处理

[root@365linux ~]# perl -e 'print localtime(1279592730)."\n";'
Tue Jul 20 10:25:30 2010


系统时区设置:

[root@365linux ~]# vim /etc/sysconfig/clock ZONE="Asia/Shanghai"
UTC=true
ARC=false
[root@365linux ~]# cp /usr/share/zoneinfo/Asia/Shanghai  /etc/localtime


oracle 中将unix/linux时间戳进行转换

unix/linux时间戳转换为标准时间格式(主要是注意时区问题):

select TO_DATE('19700101','yyyymmdd') + 1235728935/86400 +TO_NUMBER(SUBSTR(TZ_OFFSET(sessiontimezone),1,3))/24 from dual


其中1235728935就是unix/linux时间戳,转换完之后就表示为 2009-2-27 18:02:15。反过来也一样,还是要考虑时区:

select (to_date('2009-2-27 18:02:15','yyyy-mm-dd hh24:mi:ss') - to_date('1970-1-1','yyyy-mm-dd'))*86400- TO_NUMBER(SUBSTR(TZ_OFFSET(sessiontimezone),1,3))*3600 from dual


六、参考文档:

http://www.cnblogs.com/yaozhongxiao/archive/2013/04/14/3020353.html

http://www.ibm.com/developerworks/cn/linux/1307_liuming_linuxtime1/

http://www.ibm.com/developerworks/cn/linux/1308_liuming_linuxtime3/

http://blog.csdn.net/mcgrady_tracy/article/details/15501835
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息