JavaSE8-The New Date and Time API(1)
時間流逝,就像一支弓箭。我們很容易設定一個開始,並向前或向後以秒為單位計數。這樣說來的話,為何處理時間如此難呢?真正的問題在於人。如果我們可以簡單地告訴別人:“在1371409200秒這個時間來見我,不要遲到了”,所有的問題都變得很簡單。但是我們想把時間和白晝,季節相關聯起來,這才是使事情複雜起來的原因所在。Java1.1有一個日期類,事後看來非常的幼稚,隨著Java1.1中Calendar類的出現,裡面大部分的方法都被棄用。它的API不是很好,例項是可變化的,它不用跳動的秒來處理事務。第三次的改變在Jave8,Jave.time API出現,它糾正了過去的缺陷,將在很長一段時間為我們服務。在本章,你將學習為何時間運算如此繁瑣,新的日期和時間API如何解決這些問題。
本章要點:
1.所有java.time物件是不可變的
2.Instant(瞬時)是時間邊界的一個點(類似Date)
3.Java中,每天有86400秒
4.兩個instant的不同之處在於他們持續間隔的時間
5.LocalDateTime沒有時間時區資訊
6.TemporalAdjuster方法處理常見的Calendar運算,比如查詢一個月中第一個星期二
7.ZoneDateTime是給定時區的一個時間點(類似於GregorianCalendar)
8.增加時區時間時,為了儲存白天時間變化,實用Period,而不是Duration
9.用DateTimeFormatter來格式化和轉換日期和時間
5.1 時間邊界
歷史上,基本的時間單元秒,起源於地球圍繞軸線的旋轉。一次公轉需要24小時或24*60*60=86400秒。看起來,似乎這是一個天文上的測定,來精確定義秒。不幸的是,地球存在輕微的擺動,所以需要更精確的定義。在1967年,對於秒的新的精確定義出現,它起源於銫放射性元素的原子的本質屬性,並且和歷史上的定義匹配。從那以後,官方時間以原子鐘網路來定義。
偶爾,官方時間維護人員需要同步絕對時間,以和地球旋轉一致。首先,官方的秒是輕微矯正過的,從1972年開始。跳動的秒偶爾被加進去。(理論上,1秒有時需要被減掉,不過此前這還沒有發生過)有一個改變系統的討論。顯然,跳動的時間是個痛點。許多計算機系統實用“矯正”的方式來保證一天86400秒,即在跳動的秒數出現前,人工的變快或變慢。這種方式之所以有效是因為計算機上的本地時間並不是總是很精確,許多計算機用外部的服務來同步本地時間。
Java的日期時間API需要Java實用以下時間範圍:
1.一天有86400s
2.每天中午和官方時間精確匹配
3.以一種精確定義的方式,嚴密地匹配該時間
以上給予Java一定的靈活性來適應未來官方時間的變化
在Java中,Instant代表時間邊界的一個點。開始時候,紀元是被任意設定在1970年1月1日凌晨,此時子午線穿過位於倫敦的格林尼治皇家天文臺。在Unix或POSIX時間裡使用同樣的慣例。從那以後,時間被定為一天86400秒,以納秒的精度向前或向後計算。Instant值向前追溯到十億年前遙遠(即Instant.MIN),它不足以表示宇宙的誕生時間(大約130.5億年前左右),但在實際應用中足夠了。畢竟,十億年前,地球被冰雪覆蓋,居住著今天動植物的祖先,他們在顯微鏡下才能看到。最大值是Instant.MAX,是1000,000,000年12月31日.靜態方法Instant.now()表示當前時間。你可以像往常一樣用equals和compareTo方法比較當前時間,這樣的話,你可以把instant當做時間戳。
為了找到兩個Instant的不同,使用靜態方法Duration.between.以正在執行的時間演算法來舉例說明
Instant start = Instant.now();
runAlgorithm();
Instant end = Instant.now();
Duration timeElapsed = Duration.between(start, end);
long millis = timeElapsed.toMillis();
Table 5–1Arithmetic Operations for Time Instants and Durations
Method Description
plus, minus:
Adds a duration to, or subtracts a durationfrom, this Instant or Duration.
plusNanos, plusMillis, plusSeconds,plusMinutes, plusHours, plusDays:
Adds a number of the given time units to thisInstantorDuration.
minusNanos, minusMillis, minusSeconds,minusMinutes, minusHours, minusDays:
Subtracts a number of the given time unitsfrom thisInstantor Duration.
multipliedBy, dividedBy, negated:
Returns a duration that is obtained by multiplying or dividing thisDurationby a ,givenlong, or by –1. Note that you can scale,only durations, not instants.
isZero, isNegativ:
Checks whether thisDurationis zero or negative.
Duration是兩個Instant的時間差,你可以計算出Duration用常見的單位,比如納秒,毫秒,秒,分,時,天等
Durations需要多個long型別的值在內部進行儲存。秒數被儲存到一個long型別中,納秒被存到其他的int型別中。如果你需要以納秒的精度進行運算,你需要Duration的全部變化範圍。你可以用下表的方法,反之,直接用toNanos()以long型別精度進行運算即可。
NOTE:納秒填充long需要300年
比如你想驗證一個演算法比其他演算法快十倍,可以用以下方式:
Duration timeElapsed2 = Duration.between(start2, end2);
boolean overTenTimesFaster =
timeElapsed.multipliedBy(10).minus(timeElapsed2).isNegative();
// Or timeElapsed.toNanos() * 10 < timeElapsed2.toNanos()
注意:Instant和Duration類是不可變的(final?),所有的方法將會產生新的例項