【Joda-Time 與 JSR310 】(4)使用 JDK8 日期時間 API
【Joda-Time 與 JSR310 】(3)使用 Joda-Time << 前情 Joda-Time 的創建者 Stephen Colebourne 參與了 JSR310,也就是 Java 標準的日期與時間 API 規格之制訂,預計在 JDK8 中一併釋出,為什麼 Stephen Colebourne 不直接將 Joda-Time 放入 Java 標準呢?在他的 Why JSR-310 isn’t Joda-Time 中做了解釋,最主要的是 Stephen Colebourne 認為 Joda-Time 有一些設計上欠周詳的缺點:
以下逐一來探討,並看看 JSR310 中會怎麼改正 … 避免 NullsJoda-Time 中有些 API 接受 清楚區隔人類與機器時間概念人類與機器對時間的觀點截然不同。對機器來說,時間就是不斷增加的數字,以 Java 來說,就是 January 1, 1970, 00:00:00 GMT(實際上是 UTC)經過的毫秒數;對人類來說,對時間的概念有年曆,有年、月、日、時、分、秒,還加上了時區等概念。 在 Joda-Time 中, 在 JSR310 中,特意讓機器與人類對時間概念的界線變得分明。JSR310 的套件命名從 對於人類的時間概念,像是日期與時間,JSR310 有 對於時間的量,Joda-Time 有 Duration 的概念,JSR310 中也有,以類別 可以發表,Joda-Time 中的一些概念,經過調整後,依舊可對應至 JSR310,程式碼使用上也類似,來看看實際的程式碼範例。底下是 Joda-Time 中要取得兩個日期間經過幾年的程式碼: Years years = Years.yearsBetween( DateTime.parse("1975-05-26"), DateTime.now()); System.out.printf("你今年的歲數為:%d%n", years.getYears()); 改成 JSR310 的話,長得也蠻類似的: Period period = Period.between(LocalDate.parse("1975-05-26"), LocalDate.now()); System.out.printf("你今年的歲數為:%d%n", period.getYears()); Joda-Time 中以建構 LocalDate javaTwoDate = new LocalDate(2013, 8, 2); System.out.printf("Taiwan Java Developer Day is %s.%n", javaTwoDate); JSR310 中常見到工廠方法建立相關實例: System.out.printf("Taiwan Java Developer Day is %s.%n", LocalDate.of(2013, 8, 2)); Joda-Time 中對日期進行運算的例子是這樣的: LocalDate birthDate = new LocalDate(1975, 5, 26); System.out.println(birthDate .plusDays(5) .plusMonths(6) .plusWeeks(3).toString("E MM/dd/yyyy")); 透過 Joda-Time 中 LocalDate birthDate = new LocalDate(1975, 5, 26); System.out.println(birthDate .plus(days(5)) .plus(months(6)) .plus(weeks(3)).toString("E MM/dd/yyyy")); 這是因為 在 JSR310 中,則可以寫成這樣: LocalDate birthDate = LocalDate.of(1975, 5, 26); System.out.println(birthDate .plus(5, DAYS) .plus(6, MONTHS) .plus(3, WEEKS).format(ofPattern("E MM/dd/yyyy"))); JSR310 中,UTC 偏移量與時區的概念是分開的。 Instant now = Instant.now(); OffsetDateTime offsetDateTime = now.atOffset(ZoneOffset.UTC); ZonedDateTime zonedDateTime = now.atZone(ZoneId.of("Asia/Taipei")); 類似地,如果有個人類時間概念的 LocalDate nowDate = LocalDate.now(); LocalTime nowTime = LocalTime.now(); OffsetDateTime offsetDateTime = OffsetDateTime.of(nowDate, nowTime, ZoneOffset.UTC); ZonedDateTime zonedDateTime = ZonedDateTime.of(nowDate, nowTime, ZoneId.of("Asia/Taipei")); 改善內部實作彈性Joda-Time 有些實作上缺乏彈性或是複雜。舉例而言,如果你仔細察看過 Joda-Time 的 API,可以發現有些操作在各類別重複了,像是 JSR310 將 API 上的操作抽取出來獨立定義,放置在
有趣的是, 來看看
操作時必須有時間的量,這是由 如果只是想調整某個日期或時間欄位,可以使用 如果你需要更複雜的調整,可以使用 單一年曆系統設計內部實作除了上述問題之外,也有年曆系統複雜及容易引發誤用的問題,Stephen Colebourne 以下列程式碼為例, int month = dateTime.getMonthOfDay(); 如果 JSR310 採單一年曆系統設計,也就是說,事實上 總結簡單來說,使用 JDK 現有的 不單只是 Java 會面臨【Joda-Time 與 JSR310 】系列中談到的問題,其他語言生態系在處理日期時間時,也會遇到類似問題,以下是一些剛好我有看過的替代程式庫參考:
以下是這系列在準備過程中,一些可以參考的文件來源:
|