Java基礎之如何取舍Joda與 Java8 日期庫


在 Java8 以前,時間和日期的類庫很難用,而且有線程安全等諸多問題。

Joda time 彌補了 Java 在這方面的不足,但是在 Java8 時,增加了 java.time 包,對 Java 在日期 API 方面的進行了增強,這些代碼實現了 JSR-310 的標准。Joda 的官方推薦遷移到 Java8 的時間類庫上來。

 

下面來詳細對比對比一下兩個類庫,看看 Java8 的日期 API 是否能真正替代 Joda time。

基礎概念對比

Joda Date 的核心概念,這些概念在 java time 中基本也能找到對應:

instant

表示一個時刻,使用從 1970-01-01 00:00:00 至今的毫秒數表示

Joda time:

DateTime dt = new DateTime(); Instant instant = dt.toInstant(); 復制代碼

Java time:

Clock clock = Clock.systemDefaultZone();
Instant instant = clock.instant(); 復制代碼

interval

表示兩個 instant 之間的間隔,左閉右開。

Joda time:

DateTime dt = new DateTime(); DateTime dt1 = new DateTime(); Interval interval = new Interval(dt.toInstant(), dt1.toInstant()); 復制代碼

java time 中沒有提供類似的 API,因為 JSR-310 標准中沒有這個概念。

duration

用毫秒表示的時間段,通常從 interval 獲得 Joda time:

Java time:

LocalDateTime l1 = LocalDateTime.now();
LocalDateTime l2 = LocalDateTime.now(); Period period = Period.between(l1.toLocalDate(), l2.toLocalDate()); 復制代碼

period

同樣表示時間段,比如 3年,5個月,而 duration 使用毫秒表示

Joda time:

DateTime dt1 = new DateTime(); DateTime dt2 = new DateTime(); Period period = Period.fieldDifference(dt1.toLocalDateTime(), dt2.toLocalDateTime()); 復制代碼

Java time:

LocalDateTime l1 = LocalDateTime.now();
LocalDateTime l2 = LocalDateTime.now(); Period period = Period.between(l1.toLocalDate(), l2.toLocalDate()); 復制代碼

chronology

年表,這是 joda-time 設計的基礎

Joda time:

DateTime dt = new DateTime(); Chronology chronology = dt.getChronology(); 復制代碼

Java time:

LocalDateTime localDateTime = LocalDateTime.now();
Chronology ch = localDateTime.getChronology(); 復制代碼

timezones

表示時區。

Joda time:

DateTime dt = new DateTime(); DateTimeZone dateTimeZone = dt.getZone(); Set<String> zones = DateTimeZone.getAvailableIDs(); 復制代碼

Java time:

Clock clock = Clock.systemDefaultZone();
ZoneId zoneId = clock.getZone();
Set<String> zones = ZoneId.getAvailableZoneIds(); 復制代碼

從上面可以看到,除了 JSR-310 中沒有的 Interval 的定義之外,這兩個庫在基礎概念方面的實現相差不大。

因為 Unix 系統從 1970-01-01 00:00:00 開始計時,這個時間也稱之為 Epoch Time,后續使用 Unix 的這種計時方式。

具體使用

Joda time 依賴 JDK5 及后續版本,沒有額外的依賴。

為了起到對比的效果,挑幾個比較常用的場景進行對比:

  • 獲取 1970 至今的毫秒數
  • 獲取當前時間
  • 獲取年、月、日、星期幾
  • 日期的增減
  • 日期的格式化

獲取時間戳

在代碼中,經常會使用這個功能來表示唯一性:

Joda time:

DateTime dt = new DateTime(); long mills = dt.getMillis(); 復制代碼

Java time:

Clock clock = Clock.systemDefaultZone();
long mills = clock.millis(); 復制代碼

獲取當前時間

這塊兩個庫沒有太大的差異:

Joda time:

DateTime dt = new DateTime(); LocalDateTime localDateTime = dt.toLocalDateTime(); 復制代碼

Java time:

LocalDateTime localDateTime = LocalDateTime.now();
復制代碼

獲取年、月、日、星期幾

Joda time:

DateTime dt = new DateTime(); int dayOfYear = dt.getDayOfYear(); int dayOfMonth = dt.getDayOfMonth(); int dayOfWeek = dt.getDayOfWeek(); int hourOfDay = dt.getHourOfDay(); 復制代碼

Java time:

Clock clock = Clock.systemDefaultZone();
LocalDateTime localDateTime = LocalDateTime.now(clock);
int dayOfYear = localDateTime.getDayOfYear(); int dayOfMonth = localDateTime.getDayOfMonth(); int dayOfWeek = localDateTime.getDayOfWeek().getValue(); int hourOfDay = localDateTime.getHour(); 復制代碼

獲取這些值兩個庫也沒有太大的差異,但是對於一些場景,比如我想獲得 "星期四" 這個字符串。 在 Joda 庫中,可以 dt.dayOfWeek().getAsShortText(); // 星期四 這樣獲得。在 Java 中,localDateTime.getDayOfWeek().name(); //THURSDAY 只能獲取到英文。

Joda time 在本地化方面比 Java time做的更好。

日期增減

Joda time:

DateTime dt = new DateTime(); dt = dt.plusDays(2); //當前日期添加兩天 dt = dt.plusHours(5); // 當前時間加上兩個小時 dt = dt.minusDays(1); // 當前日期減一天 dt = dt.minusHours(2); // 當前日期減兩個小時 復制代碼

Java time:

LocalDateTime localDateTime = LocalDateTime.now();
localDateTime = localDateTime.plusDays(2); // 增加兩天 localDateTime = localDateTime.plusHours(2); // 增加兩個小時 localDateTime = localDateTime.minusDays(1); //減少一天 localDateTime = localDateTime.minusHours(1); // 減少一個小時 復制代碼

日期的格式化

日期格式化是日常使用最頻繁的功能,下面來對比一下這兩者的區別。

Joda time:

// 方式一
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"); DateTime dt = new DateTime(); System.out.println(dt.toString(formatter)); // 方式二 String dateFormat = "yyyy-MM-dd HH:mm:ss"; System.out.println(dt.toString(dateFormat)); 復制代碼

Java time:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localDateTime = LocalDateTime.now(); System.out.println(formatter.format(localDateTime)); 復制代碼

通過上面的對比,可以發現這兩個類庫都可以完成相同的功能。雖然在細節上是有一些細微的差別。

java.util.Date 是 Java 中最早的日期類,后來就不推薦使用這個類了,java.util.Calendar 用來替代 Date。Calendar 有 Date 的所有功能,並且提供了更加豐富的獲取年月日的 API。

Calendar 是一個虛擬類,GregorianCalendar 則是 Calendar 的實現類。

Java time 與 java.util 下的時間類相互轉化,可以將 Date 或者 Calendar 轉化成 Java time 中的 LocalDateTime.

java.util.Date 轉 java.time.LocalDateTime:

Date date = new Date(); LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); 復制代碼

java.util.Carlendar 轉 java.time.LocalDateTime:

Calendar calendar = Calendar.getInstance();
LocalDateTime localDateTime = LocalDateTime.ofInstant(calendar.toInstant(), ZoneId.systemDefault());
復制代碼

Joda time 也可以與 java.util.Date 可以進行相互的轉化:

// from Joda to JDK
DateTime dt = new DateTime(); Date jdkDate = dt.toDate(); // from JDK to Joda dt = new DateTime(jdkDate); // from Joda to JDK DateTime dt = new DateTime(); Calendar jdkCal = dt.toCalendar(Locale.CHINESE); // from JDK to Joda dt = new DateTime(jdkCal); // from Joda to JDK DateTime dt = new DateTime(); GregorianCalendar jdkGCal = dt.toGregorianCalendar(); // from JDK to Joda dt = new DateTime(jdkGCal); 復制代碼

設計思想

Joda time 與 Java time 在功能上已經相差不大,常用的功能這兩個類庫都可以完成,而且兩個庫都是線程安全的。

但我認為 Joda time 的 API 更加簡潔一些,Joda time 的使用可以直接從 DateTime 這個類開始。而 Java time 的使用則更加繁瑣。

從設計上來說 Java time 都不再使用 new 來創建實例,而是使用工廠方法來創建實例。這點上比 Joda time 的設計要更好,而且更加安全。

既然 Joda time 都推薦遷移回 Java time 了,那么最終肯定是要遷移的。但是目前來說,我覺得 Joda time 用起來更加順手一些,暫時還會繼續使用這個。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM