任何企業應用程序都須要處理時間問題。應用程序須要知道當前的時間點和下一個時間點,有時它們還必須計算這兩個時間點之間的路徑。使用 JDK 完成這項任務將很是痛苦和繁瑣。如今來看看 Joda Time,一個面向 Java™ 平臺的易於使用的開源時間/日期庫。正如您在本文中瞭解的那樣,Joda-Time 輕鬆化解了處理日期和時間的痛苦和繁瑣。java
在編寫企業應用程序時,我經常須要處理日期。而且在個人最新項目中 — 保險行業 — 糾正日期計算尤爲重要。使用 java.util.Calendar
讓我有些不安。若是您也曾使用這個類處理過日期/時間值,那麼您就知道它使用起來有多麻煩。所以當我接觸到 Joda-Time — 面向 Java 應用程序的日期/時間庫的替代選擇 — 我決定研究一下。其結果是:我很慶幸我這麼作了。算法
Joda-Time 令時間和日期值變得易於管理、操做和理解。事實上,易於使用是 Joda 的主要設計目標。其餘目標包括可擴展性、完整的特性集以及對多種日曆系統的支持。而且 Joda 與 JDK 是百分之百可互操做的,所以您無需替換全部 Java 代碼,只須要替換執行日期/時間計算的那部分代碼。安全
Joda 其實是涵蓋衆多用於 Java 語言的替代 API 的大型項目,所以從技術上講,使用 Joda 和 Joda-Time 名稱表示相同的意思是一種誤稱。但在撰寫本文之際,Joda-Time API 目前彷佛是惟一處於活躍開發狀態下的 Joda API。考慮到 Joda 大型項目的當前狀態,我想將 Joda-Time 簡稱爲 Joda 應該沒什麼問題。框架
爲何要使用 Joda?考慮建立一個用時間表示的某個隨意的時刻 — 好比,2000 年 1 月 1 日 0 時 0 分。我如何建立一個用時間表示這個瞬間的 JDK 對象?使用 java.util.Date
?事實上這是行不通的,由於自 JDK 1.1 以後的每一個 Java 版本的 Javadoc 都聲明應當使用 java.util.Calendar
。Date
中不同意使用的構造函數的數量嚴重限制了您建立此類對象的途徑。函數
然而,Date
確實有一個構造函數,您能夠用來建立用時間表示某個瞬間的對象(除 「如今」 之外)。該方法使用距離 1970 年 1 月 1 日子時格林威治標準時間(也稱爲 epoch)以來的毫秒數做爲一個參數,對時區進行校訂。考慮到 Y2K 對軟件開發企業的重要性,您可能會認爲我已經記住了這個值 — 可是我沒有。Date
也不過如此。工具
那麼 Calendar
又如何呢?我將使用下面的方式建立必需的實例:spa
Calendar calendar = Calendar.getInstance(); calendar.set(2000, Calendar.JANUARY, 1, 0, 0, 0); |
使用 Joda,代碼應該相似以下所示:插件
DateTime dateTime = new DateTime(2000, 1, 1, 0, 0, 0, 0); |
Joda 使用如下概念,它們能夠應用到任何日期/時間庫:線程
我將針對 Joda 依次討論每個概念。設計
我在本文討論的 Joda 類具備不可變性,所以它們的實例沒法被修改。(不可變類的一個優勢就是它們是線程安全的)。我將向您展現的用於處理日期計算的 API 方法所有返回一個對應 Joda 類的新實例,同時保持原始實例不變。當您經過一個 API 方法操做 Joda 類時,您必須捕捉該方法的返回值,由於您正在處理的實例不能被修改。您可能對這種模式很熟悉;好比,這正是 java.lang.String
的各類操做方法的工做方式。
Instant
表示時間上的某個精確的時刻,使用從 epoch 開始計算的毫秒錶示。這必定義與 JDK 相同,這就是爲何任何 Joda Instant
子類均可以與 JDK Date
和 Calendar
類兼容的緣由。
更通用一點的定義是:一個瞬間 就是指時間線上只出現一次且惟一的一個時間點,而且這種日期結構只能以一種有意義的方式出現一次。
一個局部時間,正如我將在本文中將其稱爲局部時間片斷同樣,它指的是時間的一部分片斷。瞬間性指定了與 epoch 相對的時間上的一個精確時刻,與此相反,局部時間片斷指的是在時間上能夠來回 「移動」 的一個時刻,這樣它即可以應用於多個實例。好比,6 月 2 日 能夠應用於任意一年的 6 月份(使用 Gregorian 日曆)的次日的任意瞬間。一樣,11:06 p.m. 能夠應用於任意一年的任意一天,而且天天只能使用一次。即便它們沒有指定一個時間上的精確時刻,局部時間片斷仍然是有用的。
我喜歡將局部時間片斷看做一個重複週期中的一點,這樣的話,若是我正在考慮的日期構建能夠以一種有意義的方式出現屢次(即重複的),那麼它就是一個局部時間。
Joda 本質 — 以及其設計核心 — 的關鍵就是年表(它的含義由一個同名抽象類捕捉)。從根本上講,年表是一種日曆系統 — 一種計算時間的特殊方式 — 而且是一種在其中執行日曆算法的框架。受 Joda 支持的年表的例子包括:
Joda-Time 1.6 支持 8 種年表,每一種均可以做爲特定日曆系統的計算引擎。
時區是值一個相對於英國格林威治的地理位置,用於計算時間。要了解事件發生的精確時間,還必須知道發生此事件的位置。任何嚴格的時間計算都必須涉及時區(或相對於 GMT),除非在同一個時區內發生了相對時間計算(即時這樣時區也很重要,若是事件對於位於另外一個時區的各方存在利益關係的話)。
DateTimeZone
是 Joda 庫用於封裝位置概念的類。許多日期和時間計算均可以在不涉及時區的狀況下完成,可是仍然須要瞭解 DateTimeZone
如何影響 Joda 的操做。默認時間,即從運行代碼的機器的系統時鐘檢索到的時間,在大部分狀況下被使用。
談到日期處理,Joda 是一種使人驚奇的高效工具。不管您是計算日期、打印日期,或是解析日期,Joda 都將是工具箱中的便捷工具。在本文中,我首先介紹了 Joda,它能夠做爲 JDK 日期/時間庫的替代選擇。而後介紹了一些 Joda 概念,以及如何使用 Joda 執行日期計算和格式化。
Joda-Time 衍生了一些相關的項目,您可能會發現這些項目頗有用。如今出現了一個針對 Grails Web 開發框架的 Joda-Time 插件。joda-time-jpox 項目的目標就是添加一些必需的映射,以使用 DataNucleus 持久化引擎持久化 Joda-Time 對象。而且,一個針對 Google Web Toolkit(也稱爲 Goda-Time)的 Joda-Time 實現目前正在開發當中