轉載:http://www.open-open.com/lib/view/open1348032952724.html
任何企業應用程式都需要處理時間問題。應用程式需要知道當前的時間點和下一個時間點,有時它們還必須計算這兩個時間點之間的路徑。使用 JDK 完成這項任務將非常痛苦和繁瑣。現在來看看 Joda Time,一個面向 Java™ 平臺的易於使用的開源時間/日期庫。正如您在本文中瞭解的那樣,Joda-Time 輕鬆化解了處理日期和時間的痛苦和繁瑣。
在編寫企業應用程式時,我常常需要處理日期。並且在我的最新專案中 — 保險行業 — 糾正日期計算尤其重要。使用 java.util.Calendar
讓我有些不安。如果您也曾使用這個類處理過日期/時間值,那麼您就知道它使用起來有多麻煩。因此當我接觸到 Joda-Time — 面向 Java 應用程式的日期/時間庫的替代選擇 — 我決定研究一下。其結果是:我很慶幸我這麼做了。
Joda-Time 令時間和日期值變得易於管理、操作和理解。事實上,易於使用是 Joda 的主要設計目標。其他目標包括可擴充套件性、完整的特性集以及對多種日曆系統的支援。並且 Joda 與 JDK 是百分之百可互操作的,因此您無需替換所有 Java 程式碼,只需要替換執行日期/時間計算的那部分程式碼。
本文將介紹並展示如何使用它。我將介紹以下主題:
- 日期/時間替代庫簡介
- Joda 的關鍵概念
- 建立 Joda-Time 物件
- 以 Joda 的方式操作時間 style
- 以 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
又如何呢?我將使用下面的方式建立必需的例項:
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); |
這一行簡單程式碼沒有太大的區別。但是現在我將使問題稍微複雜化。假設我希望在這個日期上加上 90 天並輸出結果。使用 JDK,我需要使用清單 1 中的程式碼:
清單 1. 以 JDK 的方式向某一個瞬間加上 90 天並輸出結果
Calendar calendar = Calendar.getInstance(); calendar.set(2000, Calendar.JANUARY, 1, 0, 0, 0); SimpleDateFormat sdf = new SimpleDateFormat("E MM/dd/yyyy HH:mm:ss.SSS"); calendar.add(Calendar.DAY_OF_MONTH, 90); System.out.println(sdf.format(calendar.getTime())); |
使用 Joda,程式碼如清單 2 所示:
清單 2. 以 Joda 的方式向某一個瞬間加上 90 天並輸出結果
DateTime dateTime = new DateTime(2000, 1, 1, 0, 0, 0, 0); System.out.println(dateTime.plusDays(90).toString("E MM/dd/yyyy HH:mm:ss.SSS"); |
兩者之間的差距拉大了(Joda 用了兩行程式碼,JDK 則是 5 行程式碼)。
現在假設我希望輸出這樣一個日期:距離 Y2K 45 天之後的某天在下一個月的當前周的最後一天的日期。坦白地說,我甚至不想使用 Calendar
處理這個問題。使用 JDK 實在太痛苦了,即使是簡單的日期計算,比如上面這個計算。正是多年前的這樣一個時刻,我第一次領略到 Joda-Time 的強大。使用 Joda,用於計算的程式碼如清單 3 所示:
DateTime dateTime = new DateTime(2000, 1, 1, 0, 0, 0, 0); System.out.println(dateTime.plusDays(45).plusMonths(1).dayOfWeek() .withMaximumValue().toString("E MM/dd/yyyy HH:mm:ss.SSS"); |
清單 3 的輸出為:
Sun 03/19/2000 00:00:00.000 |
如果您正在尋找一種易於使用的方式替代 JDK 日期處理,那麼您真的應該考慮 Joda。如果不是這樣的話,那麼繼續痛苦地使用 Calendar
完成所有日期計算吧。當您做到這一點後,您完全可以做到使用幾把剪刀修建草坪並使用一把舊牙刷清洗您的汽車。
JDK Calendar
類缺乏可用性,這一點很快就能體會到,而 Joda 彌補了這一不足。Joda 的設計者還做出了一個決定,我認為這是它取得成功的構建:JDK 互操作性。Joda 的類能夠生成(但是,正如您將看到的一樣,有時會採用一種比較迂迴的方式)java.util.Date
的例項(和Calendar
)。這使您能夠保留現有的依賴 JDK 的程式碼,但是又能夠使用 Joda 處理複雜的日期/時間計算。
例如,完成 清單 3 中的計算後。我只需要做出如清單 4 所示的更改就可以返回到 JDK 中:
Calendar calendar = Calendar.getInstance(); DateTime dateTime = new DateTime(2000, 1, 1, 0, 0, 0, 0); System.out.println(dateTime.plusDays(45).plusMonths(1).dayOfWeek() .withMaximumValue().toString("E MM/dd/yyyy HH:mm:ss.SSS"); calendar.setTime(dateTime.toDate()); |
就是這麼簡單。我完成了計算,但是可以繼續在 JDK 物件中處理結果。這是 Joda 的一個非常棒的特性。
Joda 使用以下概念,它們可以應用到任何日期/時間庫:
- 不可變性(Immutability)
- 瞬間性(Instant)
- 區域性性(Partial)
- 年表(Chronology)
- 時區(Time zone)
我將針對 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 支援的年表的例子包括:
- ISO(預設)
- Coptic
- Julian
- Islamic
Joda-Time 1.6 支援 8 種年表,每一種都可以作為特定日曆系統的計算引擎。
時 區是值一個相對於英國格林威治的地理位置,用於計算時間。要了解事件發生的精確時間,還必須知道發生此事件的位置。任何嚴格的時間計算都必須涉及時區(或 相對於 GMT),除非在同一個時區內發生了相對時間計算(即時這樣時區也很重要,如果事件對於位於另一個時區的各方存在利益關係的話)。
DateTimeZone
是 Joda 庫用於封裝位置概念的類。許多日期和時間計算都可以在不涉及時區的情況下完成,但是仍然需要了解 DateTimeZone
如何影響 Joda 的操作。預設時間,即從執行程式碼的機器的系統時鐘檢索到的時間,在大部分情況下被使用。
現在,我將展示在採用該庫時會經常遇到的一些 Joda 類,並展示如何建立這些類的例項。
本節中介紹的所有實現都具有若干建構函式,允許您初始化封裝的日期/時間。它們可以分為 4 個類別:
- 使用系統時間。
- 使用多個欄位指定一個瞬間時刻(或區域性時間片段),達到這個特定實現所能支援的最細粒度的精確度。
- 指定一個瞬間時刻(或區域性時間片段),以毫秒為單位。
- 使用另一個物件(例如,
java.util.Date
,或者是另一個 Joda 物件)。
我將在第一個類中介紹這些建構函式: DateTime
。當您使用其他 Joda 類的相應建構函式時,也可以使用這裡介紹的內容。
Joda 通過 ReadableInstant
類實現了瞬間性這一概念。表示時間上的不可變瞬間的 Joda 類都屬於這個類的子類。(將這個類命名為 ReadOnlyInstant
可能更好,我認為這才是設計者需要傳達的意思)。換句話說,ReadableInstant
表示時間上的某一個不可修改的瞬間)。其中的兩個子類分別為 DateTime
和 DateMidnight
:
DateTime
:這是最常用的一個類。它以毫秒級的精度封裝時間上的某個瞬間時刻。DateTime
始終與DateTimeZone
相關,如果您不指定它的話,它將被預設設定為執行程式碼的機器所在的時區。可以使用多種方式構建
DateTime
物件。這個建構函式使用系統時間:DateTime dateTime = new DateTime();
一般來講,我會盡量避免使用系統時鐘來初始化應用程式的實際,而是傾向於外部化設定應用程式程式碼使用的系統時間。樣例應用程式執行以下程式碼:DateTime dateTime = SystemFactory.getClock().getDateTime();
這使得使用不同日期/時間測試我的程式碼變得更加簡單:我不需要修改程式碼來在應用程式中執行不同的日期場景,因為時間是在SystemClock
實現的內部設定的,而不是在應用程式的內部。(我可以修改系統時間,但是那實在太痛苦了!)下面的程式碼使用一些欄位值構建了一個
DateTime
物件:DateTime dateTime = new DateTime( 2000, //year 1, // month 1, // day 0, // hour (midnight is zero) 0, // minute 0, // second 0 // milliseconds );
正如您所見,Joda 可以使您精確地控制建立
DateTime
物件的方式,該物件表示時間上的某個特定的瞬間。每一個 Joda 類都有一個與此類似的建構函式,您在此建構函式中指定 Joda 類可以包含的所有欄位。您可以用它快速瞭解特定類在哪一種粒度級別上操作。下一個建構函式將指定從 epoch 到某個時刻所經過的毫秒數。它根據 JDK
Date
物件的毫秒值建立一個DateTime
物件,其時間精度用毫秒錶示,因為 epoch 與 Joda 是相同的:java.util.Date jdkDate = obtainDateSomehow(); long timeInMillis = jdkDate.getTime(); DateTime dateTime = new DateTime(timeInMillis);
並且這個例子與前例類似,唯一不同之處是我在這裡將
Date
物件直接傳遞給建構函式:java.util.Date jdkDate = obtainDateSomehow(); dateTime = new DateTime(jdkDate);
Joda 支援使用許多其他物件作為建構函式的引數,用於建立
DateTime
,如清單 5 所示:
清單 5. 直接將不同物件傳遞給DateTime
的建構函式
// Use a Calendar java.util.Calendar calendar = obtainCalendarSomehow(); dateTime = new DateTime(calendar); // Use another Joda DateTime DateTime anotherDateTime = obtainDateTimeSomehow(); dateTime = new DateTime(anotherDateTime); // Use a String (must be formatted properly) String timeString = "2006-01-26T13:30:00-06:00"; dateTime = new DateTime(timeString); timeString = "2006-01-26"; dateTime = new DateTime(timeString);
注意,如果您準備使用
String
(必須經過解析),您必須對其進行精確地格式化。參考 Javadoc,獲得有關 Joda 的ISODateTimeFormat
類的更多資訊(參見 參考資料)。DateMidnight
:這個類封裝某個時區(通常為預設時區)在特定年/月/日的午夜時分的時刻。它基本上類似於DateTime
,不同之處在於時間部分總是為與該物件關聯的特定DateTimeZone
時區的午夜時分。
您將在本文看到的其他類都遵循與 ReadableInstant
類相同的模式(Joda Javadoc 將顯示這些內容),因此為了節省篇幅,我將不會在以下小節介紹這些內容。
應用程式所需處理的日期問題並不全部都與時間上的某個完整時刻有關,因此您可以處理一個區域性時刻。例如,有時您比較關心年/月/日,或者一天中的時間,甚至是一週中的某天。Joda 設計者使用 ReadablePartial
介面捕捉這種表示區域性時間的概念,這是一個不可變的區域性時間片段。用於處理這種時間片段的兩個有用類分別為 LocalDate
和 LocalTime
:
LocalDate
:該類封裝了一個年/月/日的組合。當地理位置(即時區)變得不重要時,使用它儲存日期將非常方便。例如,某個特定物件的出生日期 可能為 1999 年 4 月 16 日,但是從技術角度來看,在儲存所有業務值的同時不會了解有關此日期的任何其他資訊(比如這是一週中的星期幾,或者這個人出生地所在的時區)。在這種情況下,應當使用LocalDate
。樣例應用程式使用
SystemClock
來獲取被初始化為系統時間的LocalDate
的例項:LocalDate localDate = SystemFactory.getClock().getLocalDate();
也可以通過顯式地提供所含的每個欄位的值來建立
LocalDate
:LocalDate localDate = new LocalDate(2009, 9, 6);// September 6, 2009
LocalDate
替代了在早期 Joda 版本中使用的YearMonthDay
。LocalTime
: 這個類封裝一天中的某個時間,當地理位置不重要的情況下,可以使用這個類來只儲存一天當中的某個時間。例如,晚上 11:52 可能是一天當中的一個重要時刻(比如,一個 cron 任務將啟動,它將備份檔案系統的某個部分),但是這個時間並沒有特定於某一天,因此我不需要了解有關這一時刻的其他資訊。樣例應用程式使用
SystemClock
獲取被初始化為系統時間的LocalTime
的一個例項:LocalTime localTime = SystemFactory.getClock().getLocalTime();
也可以通過顯式地提供所含的每個欄位的值來建立
LocalTime
:LocalTime localTime = new LocalTime(13, 30, 26, 0);// 1:30:26PM
瞭解特定的時刻或是某個區域性時間片段將非常有用,但是如果能夠表達一段時間跨度的話,通常也很有用。Joda 提供了三個類來簡化這個過程。您可以選擇用於表示不同跨度的類:
Duration
:這個類表示一個絕對的精確跨度,使用毫秒為單位。這個類提供的方法可以用於通過標準的數學轉換(比如 1 分鐘 = 60 秒,1 天 = 24 小時),將時間跨度轉換為標準單位(比如秒、分和小時)。您只在以下情況使用
Duration
的例項:您希望轉換一個時間跨度,但是您並不關心這個時間跨度在何時發生,或者使用毫秒處理時間跨度比較方便。Period
:這個類表示與Duration
相同的概念,但是以人們比較熟悉的單位表示,比如年、月、周。您可以在以下情況使用
Period
:您並不關心這段時期必須在何時發生,或者您更關心檢索單個欄位的能力,這些欄位描述由Period
封裝的時間跨度。Interval
:這個類表示一個特定的時間跨度,將使用一個明確的時刻界定這段時間跨度的範圍。Interval
為半開 區間,這表示由Interval
封裝的時間跨度包括這段時間的起始時刻,但是不包含結束時刻。可以在以下情況使用
Interval
:需要表示在時間連續區間中以特定的點開始和結束的一段時間跨度。
現在,您已經瞭解瞭如何建立一些非常有用的 Joda 類,我將向您展示如何使用它們執行日期計算。接著您將瞭解到 Joda 如何輕鬆地與 JDK 進行互操作。
如果您只是需要對日期/時間資訊使用佔位符,那麼 JDK 完全可以勝任,但是它在日期/時間計算方面的表現十分糟糕,而這正是 Joda 的長處。我將向您展示一些簡單的例子。
假設在當前的系統日期下,我希望計算上一個月的最後一天。對於這個例子,我並不關心一天中的時間,因為我只需要獲得年/月/日,如清單 6 所示:
LocalDate now = SystemFactory.getClock().getLocalDate(); LocalDate lastDayOfPreviousMonth =\ now.minusMonths(1).dayOfMonth().withMaximumValue(); |
您可能對清單 6 中的 dayOfMonth()
呼叫感興趣。這在 Joda 中被稱為屬性(property)。它相當於 Java 物件的屬性。屬性是根據所表示的常見結構命名的,並且它被用於訪問這個結構,用於完成計算目的。屬性是實現 Joda 計算威力的關鍵。您目前所見到的所有 4 個 Joda 類都具有這樣的屬性。一些例子包括:
yearOfCentury
dayOfYear
monthOfYear
dayOfMonth
dayOfWeek
我將詳細介紹清單 6 中的示例,以向您展示整個計算過程。首先,我從當前月份減去一個月,得到 “上一個月”。接著,我要求獲得 dayOfMonth
的最大值,它使我得到這個月的最後一天。注意,這些呼叫被連線到一起(注意 Joda ReadableInstant
子類是不可變的),這樣您只需要捕捉呼叫鏈中最後一個方法的結果,從而獲得整個計算的結果。
當計算的中間結果對我不重要時,我經常會使用這種計算模式。(我以相同的方式使用 JDK 的BigDecimal
)。假設您希望獲得任何一年中的第 11 月的第一個星期二的日期,而這天必須是在這個月的第一個星期一之後。清單 7 展示瞭如何完成這個計算:
LocalDate now = SystemFactory.getClock().getLocalDate(); LocalDate electionDate = now.monthOfYear() .setCopy(11) // November .dayOfMonth() // Access Day Of Month Property .withMinimumValue() // Get its minimum value .plusDays(6) // Add 6 days .dayOfWeek() // Access Day Of Week Property .setCopy("Monday") // Set to Monday (it will round down) .plusDays(1); // Gives us Tuesday |
清單 7 的註釋幫助您瞭解程式碼如何獲得結果。.setCopy("Monday")
是整個計算的關鍵。不管中間LocalDate
值是多少,將其 dayOfWeek
屬性設定為 Monday 總是能夠四捨五入,這樣的話,在每月的開始再加上 6 天就能夠讓您得到第一個星期一。再加上一天就得到第一個星期二。Joda 使得執行此類計算變得非常容易。
下面是其他一些因為使用 Joda 而變得超級簡單的計算:
以下程式碼計算從現在開始經過兩個星期之後的日期:
DateTime now = SystemFactory.getClock().getDateTime(); DateTime then = now.plusWeeks(2); |
您可以以這種方式計算從明天起 90 天以後的日期:
DateTime now = SystemFactory.getClock().getDateTime(); DateTime tomorrow = now.plusDays(1); DateTime then = tomorrow.plusDays(90); |
(是的,我也可以向 now
加 91 天,那又如何呢?)
下面是計算從現在起 156 秒之後的時間:
DateTime now = SystemFactory.getClock().getDateTime(); DateTime then = now.plusSeconds(156); |
下面的程式碼將計算五年後的第二個月的最後一天:
DateTime now = SystemFactory.getClock().getDateTime(); DateTime then = now.minusYears(5) // five years ago .monthOfYear() // get monthOfYear property .setCopy(2) // set it to February .dayOfMonth() // get dayOfMonth property .withMaximumValue();// the last day of the month |
這樣的例子實在太多了,我向您已經知道了如何計算。嘗試操作一下樣例應用程式,親自體驗一下使用 Joda 計算任何日期是多麼有趣。
我的許多程式碼都使用了 JDK Date
和 Calendar
類。但是幸虧有 Joda,我可以執行任何必要的日期演算法,然後再轉換回 JDK 類。這將兩者的優點集中到一起。您在本文中看到的所有 Joda 類都可以從 JDK Calendar
或 Date
建立,正如您在 建立 Joda-Time 物件 中看到的那樣。出於同樣的原因,可以從您所見過的任何 Joda 類建立 JDK Calendar
或 Date
。
清單 8 展示了從 Joda ReadableInstant
子類轉換為 JDK 類有多麼簡單:
清單 8. 從 Joda DateTime
類建立 JDK 類
DateTime dateTime = SystemFactory.getClock().getDateTime(); Calendar calendar = dateTime.toCalendar(Locale.getDefault()); Date date = dateTime.toDate(); DateMidnight dateMidnight = SystemFactory.getClock() .getDateMidnight(); date = dateMidnight.toDate(); |
對於 ReadablePartial
子類,您還需要經過額外一步,如清單 9 所示:
清單 9. 建立表示 LocalDate
的 Date
物件
LocalDate localDate = SystemFactory.getClock().getLocalDate(); Date date = localDate.toDateMidnight().toDate(); |
要建立 Date
物件,它表示從清單 9 所示的 SystemClock
中獲得的 LocalDate
,您必須首先將它轉換為一個 DateMidnight
物件,然後只需要將 DateMidnight
物件作為 Date
。(當然,產生的 Date
物件將把它自己的時間部分設定為午夜時刻)。
JDK 互操作性被內建到 Joda API 中,因此您無需全部替換自己的介面,如果它們被繫結到 JDK 的話。比如,您可以使用 Joda 完成複雜的部分,然後使用 JDK 處理介面。
使用 JDK 格式化日期以實現列印是完全可以的,但是我始終認為它應該更簡單一些。這是 Joda 設計者進行了改進的另一個特性。要格式化一個 Joda 物件,呼叫它的 toString()
方法,並且如果您願意的話,傳遞一個標準的 ISO-8601 或一個 JDK 相容的控制字串,以告訴 JDK 如何執行格式化。不需要建立單獨的 SimpleDateFormat
物件(但是 Joda 的確為那些喜歡自找麻煩的人提供了一個 DateTimeFormatter
類)。呼叫 Joda 物件的 toString()
方法,僅此而已。我將展示一些例子。
清單 10 使用了 ISODateTimeFormat
的靜態方法:
DateTime dateTime = SystemFactory.getClock().getDateTime(); dateTime.toString(ISODateTimeFormat.basicDateTime()); dateTime.toString(ISODateTimeFormat.basicDateTimeNoMillis()); dateTime.toString(ISODateTimeFormat.basicOrdinalDateTime()); dateTime.toString(ISODateTimeFormat.basicWeekDateTime()); |
清單 10 中的四個 toString()
呼叫分別建立了以下內容:
20090906T080000.000-0500 20090906T080000-0500 2009249T080000.000-0500 2009W367T080000.000-0500 |
您也可以傳遞與 SimpleDateFormat
JDK 相容的格式字串,如清單 11 所示:
DateTime dateTime = SystemFactory.getClock().getDateTime(); dateTime.toString("MM/dd/yyyy hh:mm:ss.SSSa"); dateTime.toString("dd-MM-yyyy HH:mm:ss"); dateTime.toString("EEEE dd MMMM, yyyy HH:mm:ssa"); dateTime.toString("MM/dd/yyyy HH:mm ZZZZ"); dateTime.toString("MM/dd/yyyy HH:mm Z"); 09/06/2009 02:30:00.000PM 06-Sep-2009 14:30:00 Sunday 06 September, 2009 14:30:00PM 09/06/2009 14:30 America/Chicago 09/06/2009 14:30 -0500 |
檢視 Javadoc 中有關 joda.time.format.DateTimeFormat
的內容,獲得與 JDKSimpleDateFormat
相容的格式字串的更多資訊,並且可以將其傳遞給 Joda 物件的toString()
方法。
談到日期處 理,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 實現目前正在開發當中,但是在撰寫本文之際因為許可問題而被暫停。