首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 日期解析三大工具對比:SimpleDateFormat vs Joda-Time vs Apache DateUtils 處理 ISO8601

     編輯:Java 綜合教學

Java 日期解析三大工具對比:ISO8601 格式完美處理指南

測試場景

三種常見日期字符串格式:

  1. 2016-06-07T14:08:09.235+08:00 — 標準 ISO8601 (含毫秒、時區)
  2. 2016-06-07 14:08:09 — 無毫秒、無時區
  3. 2016-06-07 14:08:09.235 — 含毫秒、無時區

依賴坐標

<!-- Joda-Time (Java 8 前標準) -->
<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
    <version>2.12.7</version>
</dependency>

<!-- Apache Commons Lang3 (含 DateUtils) -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.14.0</version>
</dependency>

核心代碼對比

import java.util.Date;
import java.text.SimpleDateFormat;
import org.apache.commons.lang3.time.DateUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;

public class DateParseComparison {
    public static void main(String[] args) throws Exception {
        String iso8601 = "2016-06-07T14:08:09.235+08:00";
        String noMillis = "2016-06-07 14:08:09";
        String withMillis = "2016-06-07 14:08:09.235";

        // ========== 1. Joda-Time ==========
        // 默認支持 ISO8601,無需格式串
        Date d1 = new DateTime(iso8601).toDate();
        
        // 手動指定格式 (較繁瑣)
        Date d2 = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZZ").parseDateTime(iso8601).toDate();
        Date d3 = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").parseDateTime(noMillis).toDate();
        Date d4 = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.SSS").parseDateTime(withMillis).toDate();

        // ========== 2. JDK SimpleDateFormat ==========
        // ⚠️ 關鍵坑:時區模式是 XXX (大寫),非 ZZ!
        Date d5 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX").parse(iso8601); 
        Date d6 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(noMillis);
        Date d7 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").parse(withMillis);

        // ========== 3. Apache DateUtils ==========
        // 多格式嘗試,代碼最簡潔
        Date d8 = DateUtils.parseDate(iso8601, "yyyy-MM-dd'T'HH:mm:ss.SSSZZ");
        Date d9 = DateUtils.parseDate(noMillis, "yyyy-MM-dd HH:mm:ss");
        Date d10 = DateUtils.parseDate(withMillis, "yyyy-MM-dd HH:mm:ss.SSS");

        System.out.println("All parsed successfully!");
    }
}

關鍵差異總結

特性SimpleDateFormatJoda-TimeApache DateUtils
ISO8601 原生支持❌ 需手寫格式✅ new DateTime(str)❌ 需手寫格式
時區模式字母XXX (Java 7+)ZZZZ
線程安全❌ 非線程安全✅ DateTime 不可變✅ 靜態方法無狀態
API 設計繁瑣、易錯豐富、鏈式、領域模型工具類、多格式自動嘗試
性能基準略慢 (對象創建)快 (內部緩存格式化器)
維護狀態JDK 內建維護模式 (建議遷移 java.time)活躍維護

⚠️ SimpleDateFormat 最大坑:XXX vs ZZ

  • ZZ / Z:輸出 +0800 (無冒號),解析 ISO8601 +08:00 會失敗
  • XXX:輸出 +08:00 (帶冒號),正確解析 ISO8601 時區
  • Java 7+ 支持 XXX,Java 6 需預處理字符串插入冒號

最佳實踐建議

  1. Java 8+ 項目:直接使用 java.time 包 (Instant.parse, OffsetDateTime.parse, DateTimeFormatter.ISO_OFFSET_DATE_TIME),原生支持 ISO8601、線程安全、不可變
  2. 舊項目 (Java 6/7):
    • 首選 Joda-Time:API 完善、java.time 設計藍本、遷移平滑
    • 輕量場景:Apache DateUtils.parseDate 多格式自動嘗試,代碼極簡
    • 必須用 JDK:定義 ThreadLocal<SimpleDateFormat> 保證線程安全,格式串用 XXX
  3. 序列化框架:Jackson/Gson 默認 ISO8601,配置 DateFormat 時同樣注意 XXX

遷移對照表 (Joda-Time → java.time)

Joda-Timejava.time (Java 8+)
DateTimeZonedDateTime / OffsetDateTime
LocalDateTimeLocalDateTime
DateTimeFormat.forPatternDateTimeFormatter.ofPattern
new DateTime(str)OffsetDateTime.parse(str) / Instant.parse(str)
Period/DurationPeriod/Duration
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved