首先得理解一下關於時間表示的基本概念,不搞清楚基本概念,過段時間還會是一團糨糊。理解了基本概念后,再來看這幾個函數,就很簡單明了了。
1、基本概念:
1.UTC(universal time coordinated)稱為協調時間時,是國際無線電咨詢委員會制定和推薦的,以子午初線(經度0度)上的平均太陽時為依據,也就是英國倫暾的平均太陽時。
2.GMT(greenwitch mean time)格林威治平均時間,由於地球繞太陽的軌道不是圓形的,而且自轉軸相對軌道面是傾斜的,導致UTC的表示不是很精確,為此提出了GMT時間,通過每一年或兩年對UTC加一個閏秒完成修正,我們一般認為GMT和UTC是一樣的,下方統一稱為UTC;
3、Calendar Time:日歷時間,是用“從一個標准時間點到此時的時間經過的秒數”來表示的時間。無論哪一個時區,在同一時刻對同一個標准時間點來說,日歷時間都是一樣的。日歷時間返回自1970-1-1:00:00:00以來所經過的秒數累計值。因此,不論服務器是在那個時區(國家),同一時刻,日歷時間總是一樣的,都是相對於1970-1-1:00:00:00以來的秒數,理解這點很重要,如果不理解,想想多出來的秒數是那里來的...
4、時區(本地時間)
為了克服時間上的混亂,1884年在華盛頓召開的一次國際經度會議(又稱國際子午線會議)上,規定將全球划分為24個時區(東、西各12個時區)。規定英國(格林尼治天文台舊址)為中時區(零時區)、東1-12區,西1-12區。每個時區橫跨經度15度,時間正好是1小時。最后的東、西第12區各跨經度7.5度,以東、西經180度為界。每個時區的中央經線上的時間就是這個時區內統一采用的時間,稱為區時,相鄰兩個時區的時間相差1小時。例如,中國東8區的時間總比泰國東7區的時間早1小時,而比日本東9區的時間遲1小時。因此,出國旅行的人,必須隨時調整自己的手表,才能和當地時間相一致。
我是這樣理解的,因為時區的划分是以太陽升起的時間。比如我每天早上7點起床,8點吃早餐,9點上班。當出差美國,於是將手機/手表調到美國當地時間,依然是早上7點起床(太陽也是某個高度),8點吃早餐,9點上班。作息時間不變,可是國內是大白天的時候,美國正是深夜。在不同時區上的白天、黑夜,對個人的感受是一樣的,但日歷時間是不一樣的,兩地方的日歷時間相減得到的時間差,就是時差了。
知道UTC與地區時間,有如下的換算關系:地區時間=UTC+時區差
東區是加相應的時區差,西區是減時區差。如北京是東八區,則北京時間=UTC+8;
2、實例:本地時間 = UTC + 時差
root@ubuntu:~/vm_disk_dpdk/study# date -u; date -R
Thu Dec 24 06:27:11 UTC 2015
Wed, 23 Dec 2015 22:27:11 -0800
本機所配置的時區是西八區(負號表示為西區)
UTC時間為Dec 24 06:27:11,本地時間為23 Dec 2015 22:27:11,等於UTC-8.
root@ubuntu:~/vm_disk_dpdk/study# cp /usr/share/zoneinfo/Asia/Chongqing /etc/localtime //更改系統時區
root@ubuntu:~/vm_disk_dpdk/study# date -u; date -R
Thu Dec 24 06:53:13 UTC 2015
Thu, 24 Dec 2015 14:53:13 +0800
root@ubuntu:~/vm_disk_dpdk/study# cp /usr/share/zoneinfo/Africa/Abidjan /etc/localtime
root@ubuntu:~/vm_disk_dpdk/study# date -u; date -R
Thu Dec 24 06:54:17 UTC 2015
Thu, 24 Dec 2015 06:54:17 +0000
root@ubuntu:~/vm_disk_dpdk/study# cp /usr/share/zoneinfo/America/New_York /etc/localtime
root@ubuntu:~/vm_disk_dpdk/study# date -u; date -R
Thu Dec 24 06:55:16 UTC 2015
Thu, 24 Dec 2015 01:55:16 -0500
3、time、localtime、gmtime & ctime (man mktime能更多信息)
time函數返回的是日歷時間。
localtime&gmtime這兩個函數的參數都是日歷時間,當換算成日期、時間時,對於localtime需要考慮時區。UTC時間,就是日歷時間加上1970-1-1:00:00:00即可。
#include <time.h> #include <sys/time.h> #include <stdio.h> void test_time() { time_t tm = 1450942746; //tm = time(NULL);
printf("calendar times = %lu seconds\n", tm); printf("localtime(&tm):\t%s", asctime(localtime(&tm))); printf("gmtime(&tm):\t%s", asctime(gmtime(&tm))); printf("ctime:\t\t%s\n", ctime(&tm)); } int main() { test_time(); return 0; }
通過更改系統時區測試兩次,再次打印的gmt時間都是一樣的(因為日歷時間是一樣的),而localtime是不一樣(localtime=gmtime(UTC)+ 時區)。
root@ubuntu:~/vm_disk_dpdk/study/apue/sys_info# cp /usr/share/zoneinfo/Africa/Djibouti /etc/localtime
root@ubuntu:~/vm_disk_dpdk/study/apue/sys_info# date -R
Thu, 24 Dec 2015 10:58:39 +0300
root@ubuntu:~/vm_disk_dpdk/study/apue/sys_info# ./a.out
calendar times = 1450942746 seconds
localtime(&tm): Thu Dec 24 10:39:06 2015 //本地時間=utc+時區
gmtime(&tm): Thu Dec 24 07:39:06 2015 //兩次測試的UTC時間是一樣的
ctime: Thu Dec 24 10:39:06 2015
root@ubuntu:~/vm_disk_dpdk/study/apue/sys_info# cp /usr/share/zoneinfo/America/Grenada /etc/localtime
root@ubuntu:~/vm_disk_dpdk/study/apue/sys_info# date -R
Thu, 24 Dec 2015 03:44:40 -0400
root@ubuntu:~/vm_disk_dpdk/study/apue/sys_info# ./a.out
calendar times = 1450942746 seconds
localtime(&tm): Thu Dec 24 03:39:06 2015
gmtime(&tm): Thu Dec 24 07:39:06 2015
ctime: Thu Dec 24 03:39:06 2015
5、strftime, time、ctime、mktime (man mktime能更多信息)
time函數返回的是日歷時間。
ctime: ctime(t) 等價於 asctime(localtime(t)).
mktime函數的輸入參數應該是本地時間而非UTC時間。附:The mktime() function converts a broken-down time structure, expressed as local time, to calendar time representation.
strftime類型sprintf,格式串的定義參考man strftime
#include <time.h> #include <sys/time.h> #include <stdio.h> void test_time() { time_t tm ; tm = time(NULL); printf("calendar times = %lu seconds\n", tm); printf("mktime(localtime(&tm)):\t%lu\n", mktime(localtime(&tm))); printf("mktime(gmtime(&tm)):\t%lu\n\n", mktime(gmtime(&tm))); printf("asctime(localtime(&tm))=%s", asctime(localtime(&tm))); printf("ctime(&tm))=\t\t%s\n", ctime(&tm)); char buf[100]; strftime(buf, 100, "%a, %d %b %Y %T %z", localtime(&tm)); printf("strftime: %s\n",buf); } int main() { test_time(); return 0; }
root@ubuntu:~/vm_disk_dpdk/study/apue/sys_info# ./a.out
calendar times = 1450947508 seconds
mktime(localtime(&tm)): 1450947508 //由此可驗證,mktime輸入的應該是本地時間,此值等於之前的日歷時間
mktime(gmtime(&tm)): 1450961908 //The mktime() function converts a broken-down time structure, expressed as local time, to calendar time representation.
asctime(localtime(&tm))=Thu Dec 24 04:58:28 2015 // ctime(t) is equivalent to asctime(localtime(t))
ctime(&tm))= Thu Dec 24 04:58:28 2015
strftime: Thu, 24 Dec 2015 04:58:28 -0400