閏秒(leap second)和linux/unix時間

以前只知道有閏年,最近聽說了一個新名詞,叫閏秒。因爲它造成了我工作中的一個模塊的crash,經過不懈的google + wikipedia,終於瞭解了一二,在這裏簡單分享一下。
一. 閏秒的由來
    在現有的世界時間體系中,存在多種標準,然而用得最多的就是世界時和原子時了。世界時是根據地球自轉爲準的時間尺度,然而由於多種因素影響,因此地球自轉並不穩定,導致世界時也不是均勻的時間尺度。以原子震盪週期爲基礎,並由世界度量衡局以世界各國家實驗室原子鐘羣加權平均產生之時間尺度稱爲國際原子時。原子時相對世界時穩定,因此經過一段時間以後,國際原子時與世界時漸漸產生了不一致。爲了使生活中之自然時刻能與原子時相符合,國際另外從國際原子時(TAI)引出一計時方式,稱爲協調世界時(UTC),作爲最終之國際時刻標準。此 方式早期採用原子頻率偏調,到公元一九七二年七月一日首次改用閏秒調整,當世界協調時(UTC)與一號世界時(UT1)之差(Difference UT1, DUT1)的絕對值預期在半年或一年之內將超過0.9秒時,爲保持DUT1在0.9秒內,國際地球自轉組織(International Earth Rotation Service, IERS)便會發布閏秒通告。在當年12月31日或6月30日的最後一分鐘(UTC時間,換算北京時間爲次年1月1日上午7時59分或7月1日上午7時 59分)做閏秒調整。增加一秒時爲正閏秒,減少爲負閏秒。如果這一秒是被加載第二天的00:00:00前,則當決定加入正閏秒時,當天23:59:59的 下一秒當記爲23:59:60,然後纔是第二天的00:00:00。如果是負閏秒,23:59:58的下一秒就是第二天的00:00:00了。
    值得注意的是原子時(TAI)與世界時(UT1)分別來自於兩個互不相干的系統,雖然 協調時(UTC)基本上解決了兩者之間的協調問題,但是由於地球自轉速度越來越慢加之不均勻,按照目前情況,不能排除若干年後出現一年閏幾次甚至更多次秒 的可能性。因此IERS發佈閏秒公告的時間也是不定的。

二. linux/unix下的時間函數
    這個只是簡單介紹一下。
1. 時間是通過一個預定義類型time_t來處理,在linux系統中,它是一個長整型,與處理時間值的函數一起被定義在頭文件time.h中。
    相關的時間值處理函數:
2. time_t time(time_t *tloc);這個函數可以返回從紀元(GMT 1970年1月1日午夜0點)至今的秒數。如果參數tloc不是空指針,函數還會把返回值寫入tloc指向的位置。
3. double difftime(time_t time1, time_t time2);用於計算兩個時間值之間的差。
struct tm* gmtime(long* clock);函數原型爲struct tm* gmtime(const time_t* timep);是用於把日期和時間轉換爲格林威治(GMT)時間的函數。其中tm結構定義如下:

struct tm
{
int tm_sec;                   /* Seconds.     [0-60] (1 leap second) */
int tm_min;                   /* Minutes.     [0-59] */
int tm_hour;                  /* Hours.       [0-23] */
int tm_mday;                  /* Day.         [1-31] */
int tm_mon;                   /* Month.       [0-11] */
int tm_year;                  /* Year - 1900. */
int tm_wday;                  /* Day of week. [0-6] */
int tm_yday;                  /* Days in year.[0-365] */
int tm_isdst;                 /* DST.         [-1/0/1]*/

#ifdef __USE_BSD
long int tm_gmtoff;           /* Seconds east of UTC. */
__const char *tm_zone;        /* Timezone abbreviation. */
#else
long int __tm_gmtoff;         /* Seconds east of UTC. */
__const char *__tm_zone;      /* Timezone abbreviation. */
#endif
};

    這裏值得注意的是tm_sec,範圍允許閏秒和雙閏秒。

4. struct tm* localtime(const time_t* clock);是把紀元到當前的系統所偏移的秒數時間轉換爲日曆事件;相比上一個函數,它返回的結構中包含的值已根據當地時區和是否採用夏令做了相應的調整。
5. 還有兩個輸出更加友好的時間函數asctime和ctime,這裏就不再贅述了。

三. 操作系統中的閏秒(leap second)
1. 對於大多數新的linux內核,在設計時它們都是支持閏秒的,這一點在REHL4/5 的2.6.x內核中得到肯定。
2. 如果linux系統沒有配種某種時間同步機制(比如NTP),那麼和閏秒無關,唯一導致的結果只是系統時間會比UTC時間快一秒。
3. Window Time Service不支持閏秒,包括服務器和客戶端。

    引用了這麼多資料,只爲說明閏秒很重要,一不小心可以會影響我們系統的正常工作,如果底層模塊不支持閏秒,拋出了異常信息,上層也要注意捕獲,否則會導致系統crash,就像我工作中的模塊一樣。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章