使用 TimeUnit 進行時間轉換
1. 概述
在 Java 中處理時間和持續時間計算時, TimeUnit
枚舉提供了一種在不同單位之間執行時間轉換的便捷方法。
無論我們想要將秒數轉換為分鐘、毫秒為小時,或是執行任何其他時間單位轉換,我們都可以使用TimeUnit
來簡化程式碼,獲得準確的結果,並使內容更具可讀性。
在本教程中,我們將了解如何使用TimeUnit
在 Java 中轉換時間。
2. 理解TimeUnit
TimeUnit
是一個enum
,包含在java.util.concurrent
套件中,表示各種時間單位,範圍從奈秒到天。它提供了一組預先定義的常數,每個常數對應於一個特定的時間單位,包括:
-
DAYS
-
HOURS
-
MINUTES
-
SECONDS
-
MILLISECONDS
-
MICROSECONDS
-
NANOSECONDS
這些常數用作時間轉換的基礎。
3. 使用TimeUnit
轉換時間
要執行時間轉換,我們需要一個表示要轉換的持續時間的值,並指定要轉換為的目標單位。 TimeUnit
提供了多種在units之間轉換時間的方法,例如convert()
或toXXX()
,其中XXX
代表目標單位。
3.1.
使用convert()
方法
首先,讓我們看一下convert(long sourceDuration, TimeUnit sourceUnit)
方法,該方法將給定單位中的給定持續時間轉換為enum
值指定的單位。
讓我們將一個簡單的整數轉換為分鐘:
long minutes = TimeUnit.MINUTES.convert(60, TimeUnit.SECONDS);
assertThat(minutes).isEqualTo(1);
在此範例中,我們從60
秒的值開始,然後將其轉換為分鐘。我們指定源時間單位作為第二個參數。輸出單位始終由enum
值決定。
讓我們來看另一個例子,其中我們進行反向轉換:
long seconds = TimeUnit.SECONDS.convert(1, TimeUnit.MINUTES);
assertThat(seconds).isEqualTo(60);
正如我們所看到的, convert()
方法在不同單位之間轉換時間。
3.2.使用toXXX()
方法
現在讓我們來探索toXXX(long sourceDuration)
方法。這裡簽名中的XXX
指定了目標單元。
我們可以使用toNanos()
、 toMicros()
、 toMillis()
、 toSeconds()
、 toMinutes()
、 toHours()
和toDays().
現在讓我們使用toXXX()
方法來重寫前面的兩個片段:
long minutes = TimeUnit.SECONDS.toMinutes(60);
assertThat(minutes).isEqualTo(1);
和之前一樣,我們剛剛將60
秒轉換為分鐘。
我們可以用另一種方式轉換:
long seconds = TimeUnit.MINUTES.toMinutes(1);
assertThat(seconds).isEqualTo(60);
如預期的那樣,上面的範例產生與先前相同的結果,因此兩個簽名是等效的。但與convert()
不同的是,當我們使用toXXX()
方法時, enum
值表示來源時間單位。
4. 具體用例
現在我們知道如何使用TimeUnit
方法轉換時間,讓我們探討一些更詳細的場景。
4.1.負輸入
首先,我們檢查轉換方法是否支援負輸入值:
long minutes = TimeUnit.SECONDS.toMinutes(-60);
assertThat(minutes).isEqualTo(-1);
給定的範例表明,轉換方法也可以處理負輸入,並且傳回的結果仍然正確。
4.2.舍入處理
現在讓我們檢查一下,如果將較小的單位轉換為較大的單位,並期望得到目標非整數結果,會發生什麼情況。我們知道所有方法都只宣告long
作為回傳類型,因此無法傳回小數結果。
讓我們透過將秒轉換為分鐘來測試舍入規則:
long positiveUnder = TimeUnit.SECONDS.toMinutes(59);
assertThat(positiveUnder).isEqualTo(0);
long positiveAbove = TimeUnit.SECONDS.toMinutes(61);
assertThat(positiveAbove).isEqualTo(1);
然後,讓我們檢查負輸入:
long negativeUnder = TimeUnit.SECONDS.toMinutes(-59);
assertThat(negativeUnder).isEqualTo(0);
long negativeAbove = TimeUnit.SECONDS.toMinutes(-61);
assertThat(negativeAbove).isEqualTo(-1);
正如我們所看到的,所有轉換都處理得沒有任何錯誤。
我們應該注意到,所有方法都實作了向零捨入的規則,該規則會截斷小數部分。
4.3.溢出處理
眾所周知,所有原語都有其不能超過的值限制。但如果結果超出限制會發生什麼事?
讓我們檢查一下將天的最小和最大long
值轉換為毫秒的結果:
long maxMillis = TimeUnit.DAYS.toMillis(Long.MAX_VALUE);
assertThat(maxMillis).isEqualTo(Long.MAX_VALUE);
long minMillis = TimeUnit.DAYS.toMillis(Long.MIN_VALUE);
assertThat(minMillis).isEqualTo(Long.MIN_VALUE);
上面的程式碼執行時不會拋出任何異常。我們應該注意,結果是無效的,因為溢位結果總是被截斷為由long
原語定義的最小值或最大值。
5. 轉換為最細單位
有時,我們可能需要將持續時間轉換為TimeUnit
中可用的最精確單位,例如將秒轉換為小時、分鐘和剩餘秒數的適當組合。不幸的是,沒有方法可以做到這一點。這是因為所有轉換方法始終傳回給定持續時間內的整個週期的總數。
要將輸入轉換為最精細的單位,我們需要實作一個自訂函數。讓我們使用3672
秒的值並獲得適當的時間單位組合 - 我們期望值是1
小時、 1
分鐘和12
秒。
要提取時間,我們可以使用:
long inputSeconds = 3672;
long hours = TimeUnit.SECONDS.toHours(inputSeconds);
assertThat(hours).isEqualTo(1);
現在,如果我們想提取剩餘的分鐘,我們應該從輸入值中減去小時中包含的秒數總和,然後使用該值進行進一步操作:
long secondsRemainingAfterHours = inputSeconds - TimeUnit.HOURS.toSeconds(hours);
long minutes = TimeUnit.SECONDS.toMinutes(secondsRemainingAfterHours);
assertThat(minutes).isEqualTo(1);
我們剛剛根據輸入資料成功計算了小時和分鐘。最後,我們需要檢索剩餘的秒數。
為此,我們重複減法邏輯,並記住調整參數:
long seconds = secondsRemainingAfterHours - TimeUnit.MINUTES.toSeconds(minutes);
assertThat(seconds).isEqualTo(12);
在範例中,我們剛剛將3672毫秒轉換為最精細的單位表示形式,其中包括小時、分鐘和秒。
六,結論
在本文中,我們探討了使用 Java 中的TimeUnit
列舉來轉換時間的各種方法。
TimeUnit
枚舉提供了一種使用convert()
和toXXX()
方法在不同單位之間進行轉換的便捷高效的方法。
此外,它還處理負輸入並傳回正確的結果。我們可以輕鬆地轉換持續時間,無論我們是從較小的單位轉換為較大的單位還是反之亦然,並向零舍入。它還透過將結果修剪到邊界值來實現基本的溢出保護。
如果我們想要將來源持續時間轉換為其他單位的適當組合(例如天、小時、分鐘和秒),我們可以輕鬆實現額外的邏輯。所有轉換器都會傳回指定持續時間內指定週期的總數。
與往常一樣,範例的原始程式碼可在 GitHub 上取得。