每個程式設計師都應瞭解的關於時間的事

jobbole發表於2013-01-21

 一些關於時間的註解:

  ●UTC/協調世界時:又稱“世界標準時間”或“世界協調時間”,簡稱UTC(從英文“Coordinated Universal Time”/法文“Temps Universel Cordonné”而來),是最主要的世界時間標準,其以原子時秒長為基礎,在時刻上儘量接近於格林尼治平時。中國大陸稱之為“協調世界時”。臺灣稱之為“世界統一時間”。

  ●GMT:因為本初子午線被英國御用天文學家艾裡武斷地選定為位於英國格林尼治天文臺的一條經線, UTC 又曾稱為“格林尼治標準時間” (Greenwich Mean Time, GMT)。

設於英國格林尼治皇家天文臺大門外的24小時制電子大鐘,顯示格林尼治標準時間。

  ●其他時區都可寫為與 UTC 時間的偏移量。北京時間是 UTC+8(俗稱“東八區”)。例如某日的 00:00 UTC 是同日的北京時間 08:00。

  ●夏令時 並不影響 UTC。它只是當地政府關於改變其時區(與 UTC 的偏移量)的決定。 例如,GMT 在冬季是英國的國家時區,而夏季則選用英國夏令時(BST)。

  ●閏秒: 根據國際慣例,通過在每個 UTC 年的十二月,或者六月的最後一秒,引入一秒閏秒,來使 UTC 與物理現實(UT1,天文時間量度)保持 0.9 秒以內的差距。(UTC 完全是人類武斷的定義,而平均太陽日的長度正以非常緩慢的速度增加中)

  ●閏秒並不需提前六個月宣佈。這對於時長超過六個月的精密時間計劃是重大的問題。

  ●Unix 時間:亦或稱 POSIX時間,以 Unix 紀元初(1970年1月1日0時0分0秒)至今的總秒數度量,不包括閏秒。 Unix 時間不受時區和夏令時的影響。

Year_2038_problem 2038年問題

2038年1月19日3時14分07秒,32位系統的UNIX時間將會被重置。

   ●根據 POSIX.1 標準,Unix 時間應該通過重複前一秒處理閏秒。例如:

59.00
59.25
59.50
59.75
59.00 ← 重複
59.25
59.50
59.75
00.00 ← 增加
00.25

  這一方法有利有弊:你無法重現一個閏秒,而且時間可能會倒退;但從另一個角度來說,每天的時間卻確切為 86,400 秒長,輸出人類可讀的時分秒之時,你並不需要列出一個過去和未來的所有閏秒錶。

  ●ntpd (Network Time Protocol daemon)在從上流伺服器處接收到“閏秒位(leap bits)”後,應當完成這次時間重複。 但我也曾見過它違背這一標準:系統進入到未來的一秒,然後緩慢地偏移回正確的時間。

 每個程式設計師都應瞭解的關於時間的事:

  ●時區是一個表示層的問題!  你多數的程式碼不應處理時區或本地時問題,請總使用 Unix 時間。

  ●使用 Unix 時間作為度量,它是 UTC 時間 —— 易於獲取,而且沒有時區、夏令時(和閏秒)。

  ●儲存時間時使用 Unix 時間,它是一個整數。

  ●如果你希望儲存人類可讀的時間(例如在日誌中),考慮將其與 Unix 時間共同儲存, 而不是取代 Unix 時間。

  ●顯示時間時,同時顯示所在時區——一個未知時區偏移量的時間是無用的。

  ●系統時鐘並不精確。

  ●你在一個網路中? 那麼請注意所有系統的時鐘都有不同的不精確性。

  ●系統時鐘可以——或者會——因你所控制外的事情向後或向前跳躍。你的程式必須能夠處理這一問題。

  ●每[實際]秒的[時鐘]滴答並不精確且易變。多數情況它會隨溫度而變化。

  ●不要盲目地使用 gettimeofday()。如果你需要一個單調遞增的時鐘,選擇clock_gettime().

  ●ntpd 可以通過以下兩種方式改變系統時間:

  +跳躍: 直接將系統時鐘即時地向前或向後調整為正確時間。

  +轉換: 修改系統時鐘的頻率,使系統時間慢慢地偏移為正確時間。

  轉換這一方法破壞性較小,因而它較受歡迎。但只當修復小的時間誤差時此方法才有效。

 值得一提的:

  ●根據相對論,每個“觀察者”的“一秒鐘”都是不同的。遠端時脈頻率相對一個“觀察者”來說,受到相對速度和重力的影響。GPS 衛星中的時間已根據相對論效應調整。

  ●MySQL(高於 4.x 和 5.x 的版本)將 DATETIME 型別儲存為一個 “YYYY-MM-DD HH:MM:SS” 串的二進位制編碼。其本身並不儲存時差,使用時根據@@session.time_zone 指示時區解釋。

mysql> insert into times values(now());
mysql> select unix_timestamp(t) from times;
1310128044
mysql> SET SESSION time_zone='+0:00';
mysql> select unix_timestamp(t) from times;
1310164044

  如果你很介意這件事,那麼使用 UNIX_TIMESTAMP() 和 FROM_UNIXTIME() 函式,將時間儲存為數字。(UNIX_TIMESTAMP() 將引數時間串使用當前 time_zone 的設定解釋,並轉換為 Unix 時間數字,如果當地規定了夏令時,也將按夏令時解釋)

  還有 TIMESTAMP 型別,將時間儲存為 Unix 時間。它有不同的用法

  英文原文:unix4lyfe,編譯:@泉州一中-劉家昌  、周金宇Jered的譯文

  譯文連結:http://blog.jobbole.com/32534/

相關文章