2013-12-23 51 views
6

我正在研究Java7項目,我們需要國際原子時間的時間戳。我發現關於這一點,點JSR-310和ThreeTen項目(這是實施JSR-310),其他幾個問題:如何在Java中獲取國際原子時間7

How to get GPS Time and TAI time in Java?

http://www.coderanch.com/t/549178/java/java/TAI-Atomic-Time-International

不過,我掙扎確切地說明Java 7的用途以及從哪裏獲得它。似乎有ThreeTen的舊SourceForge & GitHub頁面,以及一個OpenJDK頁面。我已經找到了Java 7的backport,但是在從Maven下載它之後,它不包含TAIInstant類,這是我真正需要的(TIAInstant類在javax.time下的ThreeTen SourceForge JavaDoc中列出) .TAIInstant)。

爲了完整,這是從我的pom.xml摘錄:

<dependency> 
    <groupId>org.threeten</groupId> 
    <artifactId>threetenbp</artifactId> 
    <version>0.8.1</version> 
</dependency> 

我應該使用別的東西,並在那裏我應該從得到它?

注意:對不起,我無法提供指向所有網頁的鏈接,但StackOverflow不會讓我在沒有更高代表的情況下每個帖子有> 2個鏈接。

[編輯] 原因希望TAI是,我需要一個時間戳這是單調遞增的,這一點我相信TAI滿足(即使在正&負閏秒,因爲它 不關心的飛躍秒數 平均計數所有秒,包括閏秒)。

從各種來源閱讀了關於POSIX/Unix時間的信息後,我仍然不清楚Unix時代閏秒會發生什麼。我知道Unix時間在引用UTC時間方面是不明確的,但我不清楚在閏秒發生的瞬間Unix時間會發生什麼?例如,Unix時間「暫停」還是倒退?也許更重要的是,即使它不應該按照Unix時間規範,Unix的實現是否真的服從關於閏秒的規範......?

最後,我正確地說System.currentTimeMillis()會得到相當於POSIX時間(儘管以毫秒爲單位而不是秒)?

注意,我需要一個可移植到JVM和機器上的對象(排除System.nanoTime()或類似)。

[結論]

TAI
TAI是,每一個第二計數和「所有秒等於」測量時間的系統 - 即每秒鐘由相同的時間段組成,並且所有秒(包括閏秒)在總數中計數。這意味着TAI中的秒數(從某個任意起始點開始計算,例如Unix Epoch)是一個單調遞增的整數。

POSIX時間
POSIX時間是用於測量時間的標準(NOT一個實現)。它每天定義爲正好有86400秒。因此,POSIX時間不計算閏秒(因爲偶爾一分鐘可能有61秒,導致日期> 86400秒,理論上每分鐘可能有59秒,導致日期爲< 86400秒)。這意味着POSIX中的「秒」具有可變長度,並且在閏秒之前/之中/之後,POSIX時鐘可能會跳過秒或重複它們。具體而言,Meno Hochschild在他的回答中引用的POSIX規範指出:「實際時間與自Epoch未指定以來秒數的當前值之間的關係」。

UTC
UTC是它與地球繞太陽運動的方式,目的是保持太陽的位置和一天中的時間(閾值之內)之間的關係的時間標準。即在地球的UTC + 0地區,太陽始終處於世界時UTC時的最高點。閏秒(正面或負面)是必要的,因爲地球自轉的速度不是固定的,並且不會以可預測的方式變化(這意味着我們無法預測何時需要閏秒 - 或者它們是正閏秒還是閏秒負閏秒)

代表時報
這在我看來,TAI和POSIX無一不是「秒計數」表示(即東西容易對計算機的實際存儲),而UTC是一個「人時間(即年/月/日小時:分鐘:秒。毫秒)的「解釋」,通常不存儲在計算機內部。

翻譯時報
鑑於上述情況,有許多的從POSIX平移問題(不計任何閏秒)至TAI(與閏秒計算):

  1. 它需要維持表/計數閏秒翻譯任何POSIX時間到TAI時間
  2. 即使點1被解決,上述POSIX規格不能保證期間會發生什麼閏秒,所以在這樣的時候,我們沒有準確表示的方式nting明確的時間
  3. 如果多個系統必須溝通,通過他們之間的時間戳,我們必須保證閏秒錶/計數保持一致

在另一方面,很容易轉換從POSIX到UTC的「人類解讀」。它不需要知道閏秒,因爲它假設每天都有相同的秒數(儘管其中的某些「秒」在現實中具有不同的時間長度)。實際上,您只需使用POSIX Spec中公式的反函數即可獲得各種UTC時間分量(再次參見Meno Hochschild引用的POSIX規範)。

+0

[ThreeTen的SourceForge](http://sourceforge.net/apps/mediawiki/threeten/index.php?title=ThreeTen) [ThreeTen GitHub的](http://threeten.github.io/) [ThreeTen的OpenJDK](http://openjdk.java.net/projects/threeten/) [javax.time.TAIInstant的Javadoc上SourceForge](http://threeten.sourceforge.net/apidocs/index.html?javax/time/TAIInstant.html) – asibs

+0

糾正並解釋了更多。希望能幫助到你。 –

回答

3

JSR-310-backport僅支持將包含在Java 8中的功能.TAI(和真正的UTC)不會成爲受支持的功能,因此它不能在backport中。唯一的選擇是嘗試包含TAIInstant類的threeten-extra-project,但是整個extra-project可能不是最新的(非常舊的代碼)。

我自己正在研究我的庫Time4J,它除了POSIX之外還有TAI,GPS和UTC支持。

[2014年7月的更新:Time4J現已發佈爲穩定版本time4j-v1.0。這個辯論已經被考慮在內 - 例如參見Moment.toString(TimeScale) 。]


校正和詳細的言論,OP的新發布的問題:

a)是,TAI是單調的SI-秒爲單位,即使在閏秒增加。如果只是你想要的東西,你可以選擇TAI,但是有一個缺陷。如果你想描述民事時間戳,那麼TAI會給你錯誤的時間戳(只比較Wikipedia diagram的第一列和第二列)。原因很簡單,公民生活由UTC統治,而不是TAI。

b)關於我的意見,維基百科圖是錯誤的,我再次仔細看了一遍,並改變了主意。 POSIX和TAI之間的關係是不固定的(僅在1972年10s才能抵消),請原諒我的錯誤。到現在爲止,我對TAI沒有太多的瞭解,而是關於POSIX和UTC。但是,感謝這個問題和這個啓發性的辯論,所以你應該得到我的讚賞。整個事情是棘手的。當我們談論以不同時間尺度表示的時間戳時,我們需要在ymdhms-form和epochsecs-form之間做出區別。讓我們看看它在細節的時間1999-01-01T00:00:00Z(UTC-規模):

i) TAI = (29 * 365 + 7) days * 86400 + 22 leap seconds + 10s (offset at 1972) = 915148832 
ii) UTC = TAI - 10 = 915148822 (fixed relation between UTC and TAI on epoch-second-level) 
iii) POSIX = UTC - 22 leap seconds = 915148800 

=> (ymdhms-form); 
    i) TAI (915148800 + 32) = 1999-01-01T00:00:32 (based on TAI-"day" = 86400 SI-secs) 
ii) UTC = 1999-01-01T00:00:00 (stripped off former 22 leap secs in conversion to ymdhms) 
iii) POSIX = 1999-01-01T00:00:00 (fixed relation between UTC and POSIX with exception of leapsecs) 

那麼,爲什麼聲明TAI不計閏秒?它不會計算ymdhms-form中的跳躍次數,但當然它會按照時代第二級(單調性要求!)計算它們。和POSIX?它根本不計算閏秒,而是以ymdhms-form的形式出現,也不在時代的秒級上。所以最後我們在TAI和POSIX之間沒有固定的關係。轉換需要閏秒錶。

c)POSIX規範講述的是閏秒行爲?請參閱here。尤其要注意以下陳述:「自Epoch未指定以來,實際時間與當前值之間的關係(秒)」。所以這也與閏秒有關。如果它們在閏秒之前跳躍或跳躍或凍結一秒鐘,則需要時鐘實現。

d)是的,System.currentTimeMillis()將獲得相當於POSIX時間(儘管以毫秒爲單位而不是秒)。 e)值得注意的是,標籤TAI並沒有在1971年之前定義,國際原子時間也沒有在1958年之前定義過,所以3ten-extra-class TAIInstant的預測規模在某種程度上是無稽之談。所以我不會在1972年之前申請TAI。在這裏,我會和時間尺度專家史蒂夫艾倫一起去。 f)如果你需要一個「可跨JVM和機器移植」的時間對象,那麼UTC本身需要在任何地方分發/存在相同的閏秒錶。如果您選擇TAI,您仍然需要此閏秒錶以便使應用程序能夠將TAI時間戳轉換爲UTC或POSIX時間戳。所以我懷疑你可以有一個單調遞增的時間戳並且同時忽略閏秒。 TAI不爲這種困境提供解決方案。

回答以下問題/ OP的總結2013-12-31來自:

您對TAI和POSIX總結是正確的。

關於UTC,您應該首先明白UTC是一種妥協。一方面它被設計成追隨太陽,另一方面UTC時間尺度上的第二個與TAI尺度上的完全相同,即SI-second(原子定義)。當你說地球的旋轉速度不可預測地變慢時,你是對的,所以插入幾次閏秒。 UT1(平均太陽時間)與UTC之間的差值應始終小於0.9 SI-秒。因此,這與平均SI秒的事實是UTC的核心思想。另外,JSR-310中異常UTC-SLS標度的適應性與UTC的這些核心思想不兼容。關於閏秒的可預測性,BIPM在巴黎宣佈半年後如果6個月後會有閏秒需要與否,那麼你有這個六個月的可預測框架。

你可能會寫一些關於UTC部分的迂腐修正,你寫道:「太陽總是在UTC時間中午時達到最高點。」類java.nettime.Instant的javadoc中也提供了一個類似的語句,即所謂的java時標。撇開這個事實,你肯定不想說太陽的位置與你當地的位置無關,在正午的正確經度上它甚至是不正確的。爲什麼?從天文學/科學的角度來看,您應該首先不要忘記,太陽的平均太陽時間與您觀看的當地太陽時間不一樣(只是給出關鍵字「時間方程」)。此外,由於UTC仍然基於原子時間並使用原子時間進行同步,因此UT1和UTC之間存在所謂的delta-T關係。這個三角洲是在0.9secs的框架內,並由IERS/BIPM在公報B中定期發佈。當你想獲得太陽的真實位置和太陽最高時,你需要知道這個三角洲。

「代表時代」一節在我看來有點過於簡單。好的,我們可以說TAI和POSIX計算秒數,而UTC以年/月/日/...-形式表示。但是,我們的確可以將這兩種表徵應用於所有的尺度。但我們需要仔細區分這些表示形式,並徹底思考如何轉換。請注意,維基百科甚至在圖表中爲TAI選擇了ymdhms-form。那麼,電腦可以最好地存儲簡單的整數。 POSIX或TAI可以很容易地以這種格式存儲。但正如我之前所說,這些整數的解釋並不總是簡單的。在TAI的情況下,你甚至需要一個閏秒錶來轉換爲可讀的民間ymdhms-form(UTC或POSIX)。

關於下一節「翻譯時代」,我同意1-3分。

您的最後陳述「另一方面,從POSIX轉換爲UTC'人類解釋'很容易。」是正確的,除了閏秒。那麼,我在我的即將到來的圖書館中啓用了不同比例之間的適當翻譯。它有一個內置但可配置的閏秒錶,今後我還計劃使用IANA-TZDB數據作爲此表的來源。

總而言之,要了解大多數業務開發人員不需要那麼高的準確性。大多數人都會簡單地平衡POSIX和UTC,並且可能會滿足Linux操作系統或Google NTP服務器上的任何平滑硬件解決方案。真正的UTC和TAI(即考慮閏秒)需要更多的努力。所以你必須決定你的軟件架構是否需要科學的準確性。我們只需要注意,JSR-310根本沒有解決非常廣泛的POSIX規範,而是他們說,他們的Instant類應該是UTC-SLS(另請參閱這個有趣的debate)。

最後我很討論這個問題。這也幫助我在圖書館裏澄清我對TAI的想法。謝謝。

+0

感謝您的信息。我需要一個單調遞增的時間,以便幾毫秒之間的多個事件總是會有唯一的時間戳(即使涉及到閏秒)。 [用於POSIX時間的維基百科頁面](http://en.wikipedia.org/wiki/Unix_time)似乎意味着當有閏秒時(99年1月1日的例子有重複的時間戳)它不會單調增加。所以這似乎表明我不能僅僅在POSIX上添加x秒來獲得TAI(至少在閏秒事件期間)?或者我誤解了一些東西? – asibs

+0

如果你真的需要考慮閏秒,那麼TAI不適合你。然後,您需要UTC,並在後臺添加一個閏秒錶,以獲得單調遞增的時間計算閏秒。 TAI僅用於科學實驗室目的,不適用於需要UTC的民用生活。 –

+0

再次感謝,我編輯了原始問題,希望能讓事情變得更加清晰,我現在不確定的主要問題是關於POSIX/Unix時間 - 如果我們能夠(並且總是能夠)從Unix時間生成TAI時間通過減去10,那麼Unix時間也必須單調遞增。如果這是真的,那麼如果我經常從命令行調用「date +%s」,或者從閏秒(正值或負值)調用Java中的System.currentTimeMillis()等,那麼我永遠不會看到時間戳倒退。我在這個假設中糾正了錯誤還是我誤解了? – asibs

4

類別TAIInstant和其他類似UTCInstant在JSR-310過程中被刪除。該小組得出的結論是,這些都是專門的項目,不需要在覈心JDK中。我仍然相信這是正確的決定。

這樣做的結果是在JSR-310中對時間尺度的支持很少。但是,有一種正式定義的方式將JSR-310連接到時間尺度,從而在準確的源代碼下創建精確的時鐘。雖然並不是每個人都喜歡這個解決方案,但它對於主流來說是實用的

總之,UTC和TAI的獨立類的原始設計是合理的(並且是處理過去和未來事件的必要條件)。但是,它對於JDK來說太專業了。

threeten-extra項目現在可用作在用於JDK 8罐與these classes