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

Java 日期時間處理大全:Calendar、Date、格式化與計算實戰

     編輯:Java 相關知識

前言

日期時間處理是 Java 開發中高頻且易踩坑的領域。從傳統的 java.util.Date/Calendar 到現代的 java.time (JSR-310),掌握核心 API 的正確用法至關重要。本文系統梳理常見場景:月份天數計算、Date 與 Calendar 互轉、格式化輸出、週期計算、兩日期間隔天數、字符串/長整型/日期互轉,以及數據庫日期類型映射,附帶可直接運行的代碼示例。

核心場景與代碼實現

1. 獲取某月最大天數

關鍵點:Calendar 月份從 0 開始;設置字段前需 clear() 避免殘留值干擾。

Calendar cal = Calendar.getInstance();
cal.clear();
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, month - 1); // 月份 0-based
int maxDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);

2. Date 與 Calendar 互轉

// Calendar -> Date
Date date = cal.getTime();

// Date -> Calendar
Calendar cal = Calendar.getInstance();
cal.setTime(date);

3. 日期格式化輸出

使用 SimpleDateFormat,注意線程不安全,建議局部變量或使用 ThreadLocal。

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String formatted = sdf.format(new Date()); // 2024-05-20 14:30:00

4. 計算年中的第幾週 / 某週的日期

// 某天是第幾週
Calendar cal = Calendar.getInstance();
cal.set(2006, 8, 3); // 2006-09-03
int weekOfYear = cal.get(Calendar.WEEK_OF_YEAR);

// 第 1 週的周一日期
cal.set(Calendar.YEAR, 2006);
cal.set(Calendar.WEEK_OF_YEAR, 1);
cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
System.out.println(sdf.format(cal.getTime())); // 2006-01-02

5. add() 與 roll() 的區別

  • add(field, amount):修改指定字段,並自動調整更大字段(如月份進位)。
  • roll(field, amount):僅在當前字段範圍內循環,不影響更大字段。
cal.set(2006, 8, 3); // 9月3日
cal.add(Calendar.DATE, -4);  // 2006-08-30 (跨月)
cal.roll(Calendar.DATE, -4); // 2006-09-29 (同月循環)

6. 計算兩日期間隔天數

推薦:使用毫秒差值法(簡單)或 Calendar 字段法(精確跨年)。

// 方法一:毫秒差 (忽略夏令時邊界情況)
public int getIntervalDays(Date start, Date end) {
    if (start.after(end)) { Date tmp = start; start = end; end = tmp; }
    long diff = end.getTime() - start.getTime();
    return (int) (diff / (1000 * 60 * 60 * 24));
}

// 方法二:Calendar 字段法 (精確處理跨年)
public int getDaysBetween(Calendar d1, Calendar d2) {
    if (d1.after(d2)) { Calendar tmp = d1; d1 = d2; d2 = tmp; }
    int days = d2.get(Calendar.DAY_OF_YEAR) - d1.get(Calendar.DAY_OF_YEAR);
    int y2 = d2.get(Calendar.YEAR);
    if (d1.get(Calendar.YEAR) != y2) {
        d1 = (Calendar) d1.clone();
        do {
            days += d1.getActualMaximum(Calendar.DAY_OF_YEAR);
            d1.add(Calendar.YEAR, 1);
        } while (d1.get(Calendar.YEAR) != y2);
    }
    return days;
}

7. String、Date、Long 三者互轉

// String -> Date -> Long
SimpleDateFormat sdf = new SimpleDateFormat("M/dd/yyyy hh:mm:ss a", Locale.US);
Date d = sdf.parse("5/13/2003 10:31:37 AM");
long timestamp = d.getTime();

// Long -> Date -> String (指定格式)
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str = fmt.format(new Date(timestamp));

8. 解析特殊格式日期 (如年週、星期幾)

// 年週 -> 日期
SimpleDateFormat f1 = new SimpleDateFormat("yyyy-MM F E");
Date d = f1.parse("2003-05 5 星期五"); // 2003年第5週的周五

// 日期 -> 星期幾
SimpleDateFormat f2 = new SimpleDateFormat("E");
String weekDay = f2.format(d); // 星期五

9. 數據庫日期類型映射

數據庫類型Java 類型說明
Oracle DATEjava.sql.Date僅年月日
MySQL DATETIME / SQL Server DATETIMEjava.sql.Timestamp含時分秒毫秒
// 字符串 -> java.sql.Timestamp
public static Timestamp string2Time(String str) throws ParseException {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.ENGLISH);
    sdf.setLenient(false);
    return new Timestamp(sdf.parse(str).getTime());
}

// 字符串 -> java.sql.Date
public static java.sql.Date string2Date(String str) throws ParseException {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
    sdf.setLenient(false);
    return new java.sql.Date(sdf.parse(str).getTime());
}

// java.util.Date <-> Timestamp 互轉
Timestamp ts = new Timestamp(new Date().getTime()); // Date -> Timestamp
Date dt = new Date(ts.getTime()); // Timestamp -> Date

最佳實踐建議

  1. 新項目優先使用 java.time 包 (LocalDateTime, ZonedDateTime, DateTimeFormatter):不可變、線程安全、API 更豐富。
  2. 避免在多線程共享 SimpleDateFormat,改用 ThreadLocal 或每次新建。
  3. 存儲統一用 UTC 時間戳,展示層再按時區格式化。
  4. 數據庫交互:MyBatis/JPA 自動處理類型映射,手寫 JDBC 時嚴格區分 java.sql.Date 與 Timestamp。

總結

Java 日期時間處理看似繁雜,實則脈絡清晰。掌握 Calendar 字段操作、SimpleDateFormat 格式化模式、毫秒與天數換算邏輯,即可應對 90% 的業務場景。隨著 JDK 8+ 普及,建議逐步遷移至 java.time 體系,從根源上消除線程安全與 API 設計缺陷帶來的隱患。

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