天天看點

為什麼程式設計語言以及資料庫要從1970年1月1日開始計算時間【轉】

今天忽然想到這個問題,為什麼衆多程式設計語言都以 1970-01-01 00:00:00 作為計時起點??為什麼開機時間(秒)要從1970年1月1日0時開始計算??

很早以前也曾留意過這個問題,當時查過資料,但是基本忘完了,然後今天又去查閱了大量資料,很有意思,大多數人應該都不知道,結果如下:

今天在看Python  API時,看到time子產品:

The epoch is the point where the time starts. On January 1st of that year, at 0 hours,the “time since the epoch” is zero. For Unix, the epoch is 1970. To find out what the epoch is, look at gmtime(0).

定義time從1970年1月1日開始,忽然想到在JAVA裡,Oracle資料庫時間也是從1970年1月1日開始計算。

比如java類代碼

Date date = new Date(0);

System.out.println(date);

列印出來的結果:

Thu Jan 01 08:00:00 CST 1970

也是1970年1月1日,實際上時分秒是0點0分0秒(這裡列印出來是8點,稍後會作解釋)。

為什麼這個時間會定義在1970年1月1日這個時候呢?

于是開始了Google,中文網頁根本找不到答案。于是試着搜尋英文關鍵字,在Sun java論壇總算找到準确的文章:

<a href="http://forums.sun.com/thread.jspa?threadID=595140&amp;start=15" target="_blank">http://forums.sun.com/thread.jspa?threadID=595140&amp;start=15</a>

其中有一個回複:

I suspect that Java was born and raised on a UNIX system.

UNIX considers the epoch (when did time begin) to be midnight, January 1, 1970.

是說java起源于UNIX系統,而UNIX認為1970年1月1日0點是時間紀元.

但這依然沒很好的解釋"為什麼",出于好奇,繼續Google,總算找到了答案:

<a href="http://en.wikipedia.org/wiki/Unix_time" target="_blank">http://en.wikipedia.org/wiki/Unix_time</a>

這裡的解釋是:

最初計算機作業系統是32位,而時間也是用32位表示。

System.out.println(Integer.MAX_VALUE);

2147483647

Integer在JAVA内用32位表示,是以32位能表示的最大值是2147483647。另外1年365天的總秒數是31536000,

2147483647/31536000 = 68.1

也就是說32位能表示的最長時間是68年,而實際上到2038年01月19日03時14分07秒,便會到達最大時間,過了這個時間點,所有32位作業系統時間便會變為

10000000 00000000 00000000 00000000

也就是1901年12月13日20時45分52秒,這樣便會出現時間回歸的現象,很多軟體便會運作異常了。

到這裡,我想問題的答案已經出來了:

因為用32位來表示時間的最大間隔是68年,而最早出現的UNIX作業系統考慮到計算機産生的年代和應用的時限綜合取了1970年1月1日作為UNIX TIME的紀元時間(開始時間),而java自然也遵循了這一限制。

至于時間回歸的現象相信随着64為作業系統的産生逐漸得到解決,因為用64位作業系統可以表示到292,277,026,596年12月4日15時30分08秒,相信我們的N代子孫,哪怕地球毀滅那天都不用愁不夠用了,因為這個時間已經是千億年以後了。

最後一個問題:上面System.out.println(new Date(0)),列印出來的時間是8點而非0點,原因是存在系統時間和本地時間的問題,其實系統時間依然是0點,隻不過我的電腦時區設定為東8區,故列印的結果是8點。

我想以上問題如果作為面試題,也能難倒一批人了.

UNIX及Linux的時間系統是由「新紀元時間」Epoch開始計算起,機關為秒,Epoch則是指定為1970年一月一日淩晨零點零分零秒,格林威治時間。

目前大部份的UNIX系統都是用32位元來記錄時間,正值表示為1970以後,負值則表示1970年以前。我們可以很簡單地計算出其時間領域:

2^31/86400(s) = 24855.13481(天) ~ 68.0958(年)

1970+68.0958 = 2038.0958

1970-68.0958 = 1901.9042

時間領域為[1901.9042,2038.0958]。

準确的時間為2038年一月十八日星期一晚上十點十四分七秒。那一刻,時間将會轉為負數,變成1901年十二月十三日黑色星期五下午三點四十五分五十二秒,然後Jason就會跑出來用斧頭砸掉您的電腦。

這就是所謂的UNIX 2038 BUG,或者您也可戲稱為Jason hatchet bug。在大部份的UNIX上,并沒有所謂Y2K問題,不過都有2038年問題。

在一些64位元的平台上,例如Digital Alpha、SGI、Sparc等等,則用64位元來表示時間。

2^63/86400 ~ 1E14(天) ~ 2.92E11(年)

大約是292億年。

是以,使用64位元的電腦可能會有 Armageddon bug 的問題。屆時位於獵戶座旋臂的太陽,已經是黑矮星或暗黑物質,獵戶座旋臂大概也已經被重力波震斷,銀河系大概則已經變成小型似星體了。

雖然許多人認為UNIX的2038年問題會随着科技的進步,而将電腦逐漸汰換成64位元電腦,是以無須擔心。但我個人相信,在2038年,依然會有許多狀況出現。因為,就事實而言,目前許多UNIX系統都有足夠的能力服役到2038年而毫無問題。是以,如果有意添購電腦主機,而且有預期會使用到那個時候,最好是選購64位元電腦,确認隻有世界末日問題(除非您想要把資料流傳給下一個宇宙,那就要另當别論了)。

站長評論:

我勒個去,一眨眼,已經過了整整 11 年了!!原文作者不知道是否還健在,是否還在從事計算機行業,是否還在搞 Unix ……

Jason,Jason Voorhees,面具傑森魔是美國「鬼魔逍遣小說」創作出來驚悚殺人的虛構鬼物;1980年鬼片《13号星期五》是它成功問世電影,最先殺人如麻是他媽媽Mrs. Voorhees不是它,往後續集挂鐵面具的魔鬼傑森才是續列電影兇手主角;傑森魔衣衫粗布破爛褴褛、智商低笨重、大塊頭身軀從不說話、不會跑卻永遠能追到被害人,現在演殺人電影已經演到第10集,在外太空太空站拿著斬刀繼續行兇……。

Armageddon bug,意思為:世界末日的錯誤,呵呵,這是作者在搞笑。

1.3 Linux時間基準

以上我們了解了RTC(實時時鐘、硬體時鐘)和OS時鐘(系統時鐘、軟時鐘)。下面我們具體描述OS時鐘。OS時鐘是由可程式設計定時/計數器産生的輸出脈沖觸發中斷而産生的。輸出脈沖的周期叫做一個“時鐘滴答”。計算機中的時間是以時鐘滴答為機關的,每一次時鐘滴答,系統時間就會加1。作業系統根據目前時鐘滴答的數目就可以得到以秒或毫秒等為機關的其他時間格式。

定義“時間基準”的目的是為了簡化計算,這樣計算機中的時間隻要表示為從這個時間基準開始的時鐘滴答數就可以了。“時間基準是由作業系統的設計者規定的。例如DOS的時間基準是1980年1月1日,Unix的時間基準是1970年1月1日上午12點,Linux的時間基準是1970年1月1日淩晨0點。

呵呵,有意思吧……

【新浪微網誌】 張昺華--sky

【twitter】 @sky2030_

【facebook】 張昺華 zhangbinghua

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利.