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

Joda-Time 完整使用指南:日期時間處理最佳實踐 (Java 8 前最強選擇)

     編輯:Java 綜合教學

為什麼選擇 Joda-Time?

在 Java 8 引入 java.time 之前,JDK 內建 Date/Calendar API 設計缺陷眾多:不可變性差、執行緒不安全、月份 0-based、時區處理繁瑣。Joda-Time 成為事實標準,提供:

  • 不可變、執行緒安全的核心類別
  • 豐富的日期時間運算 API
  • 強大的格式化/解析支援
  • 完整的時區、紀年體系支援

Maven 依賴

<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
    <version>2.12.7</version> <!-- 建議使用最新穩定版 -->
</dependency>

核心類別速查

類別用途關鍵特性
DateTime完整日期時間 (含時區)不可變、最常用
LocalDate僅日期 (無時間、無時區)適合生日、紀念日
LocalTime僅時間 (無日期、無時區)適合鬧鐘、營業時間
LocalDateTime日期時間 (無時區)本地時區應用
DateTimeFormatter格式化/解析執行緒安全、預定義格式豐富
Period日期間隔 (年/月/日)人類認知的間隔
Duration時間間隔 (毫秒/秒/分/時)機器精確的間隔
Days/Hours/Minutes/Seconds單一單位間隔便利計算

常用操作範例大全

1. 建立與解析

// 建立特定時間
DateTime dt1 = new DateTime(2024, 7, 15, 14, 30, 0);
DateTime dt2 = new DateTime(2024, 7, 15, 14, 30, 0, 123); // 含毫秒

// 當前時間
DateTime now = DateTime.now();
DateTime utcNow = DateTime.now(DateTimeZone.UTC);

// 字串解析
DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
DateTime parsed = fmt.parseDateTime("2024-07-15 14:30:00");

// 從 JDK 物件轉換
DateTime fromJdkDate = new DateTime(new java.util.Date());
DateTime fromCalendar = new DateTime(Calendar.getInstance());
DateTime fromMillis = new DateTime(System.currentTimeMillis());

2. 格式化輸出

DateTime dt = new DateTime(2024, 7, 15, 14, 30, 0);
System.out.println(dt.toString("yyyy-MM-dd HH:mm:ss"));           // 2024-07-15 14:30:00
System.out.println(dt.toString("yyyy年MM月dd日 HH時mm分ss秒", Locale.TRADITIONAL_CHINESE)); // 中文
System.out.println(dt.toString("EEEE, MMMM dd, yyyy"));           // Monday, July 15, 2024
System.out.println(dt.toString("yyyy/MM/dd HH:mm Z"));            // 含時區偏移

3. 日期運算 (鏈式呼叫,不可變)

DateTime dt = new DateTime(2024, 7, 15, 14, 30, 0);

// 加減運算
DateTime future = dt.plusYears(1).plusMonths(2).plusDays(10).plusHours(3);
DateTime past = dt.minusWeeks(2).minusMinutes(30);

// 精確到欄位操作
DateTime firstDayOfMonth = dt.dayOfMonth().withMinimumValue();
DateTime lastDayOfMonth = dt.dayOfMonth().withMaximumValue();
DateTime nextFriday = dt.dayOfWeek().setCopy(5); // 5=Friday

4. 間隔計算

LocalDate start = new LocalDate(2024, 1, 1);
LocalDate end = new LocalDate(2024, 12, 31);

// 天數差
int days = Days.daysBetween(start, end).getDays();

// 精確間隔 (含時間)
DateTime dtStart = new DateTime(2024, 1, 1, 0, 0, 0);
DateTime dtEnd = new DateTime(2024, 12, 31, 23, 59, 59);
Duration duration = new Duration(dtStart, dtEnd);
long hours = duration.getStandardHours();
long minutes = duration.getStandardMinutes();

5. 閏年/閏月判斷

DateTime dt = new DateTime(2024, 2, 1);
boolean isLeapYear = dt.year().isLeap(); // true
boolean isLeapMonth = dt.monthOfYear().isLeap(); // false (Joda 無閏月概念,僅支援儒略/格里高利曆)

6. 與 JDK 互操作

// Joda → JDK
java.util.Date jdkDate = dateTime.toDate();
Calendar cal = dateTime.toCalendar(Locale.getDefault());
long millis = dateTime.getMillis();

// JDK → Joda
DateTime fromDate = new DateTime(jdkDate);
DateTime fromCal = new DateTime(cal);
DateTime fromMillis = new DateTime(millis);

實戰案例:計算寶寶年齡 (精確到秒)

public class BabyAgeCalculator {
    private static final DateTimeFormatter FMT_SEC = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
    private static final DateTimeFormatter FMT_DAY = DateTimeFormat.forPattern("yyyy-MM-dd");
    private static final String BIRTHDAY = "2020-03-10 08:20:55";

    public static void main(String[] args) {
        DateTime birth = FMT_SEC.parseDateTime(BIRTHDAY);
        DateTime now = DateTime.now();
        printAge(birth, now);
        
        // 模擬指定日期
        DateTime target = FMT_DAY.parseDateTime("2024-07-15").toDateTimeAtStartOfDay();
        printAge(birth, target);
    }
    
    static void printAge(DateTime start, DateTime end) {
        // 日期部分差異
        LocalDate s = start.toLocalDate();
        LocalDate e = end.toLocalDate();
        int days = Days.daysBetween(s, e).getDays();
        
        // 時間部分差異 (需處理借位)
        int hours = end.getHourOfDay() - start.getHourOfDay();
        int mins = end.getMinuteOfHour() - start.getMinuteOfHour();
        int secs = end.getSecondOfMinute() - start.getSecondOfMinute();
        
        if (secs < 0) { secs += 60; mins--; }
        if (mins < 0) { mins += 60; hours--; }
        if (hours < 0) { hours += 24; days--; }
        
        System.out.printf("已出生 %d天 %d時 %d分 %d秒%n", days, hours, mins, secs);
    }
}

遷移建議:Java 8+ 專案請改用 java.time

Joda-Time 作者 Stephen Colebourne 參與設計了 JSR-310 (java.time),兩者 API 高度相似。對照表:

Joda-Timejava.time (JDK 8+)
DateTimeZonedDateTime / OffsetDateTime
LocalDateLocalDate
LocalTimeLocalTime
LocalDateTimeLocalDateTime
DateTimeFormatterDateTimeFormatter
PeriodPeriod
DurationDuration
DateTimeZoneZoneId / ZoneOffset

新專案請直接使用 java.time;維護舊專案時 Joda-Time 仍是優秀選擇。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved