一、与时间相关的概念
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.****.net/mcgrady_tracy/article/details/15501835