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

Java Calendar 日期時間處理完整指南:核心 API 與實戰技巧

     編輯:Java 相關知識

Calendar 類概述

java.util.Calendar 是 JDK 1.1 引入的抽象類,用於日期時間運算,功能比 Date 強大,支持國際化、時區、字段操作。實際使用時獲取具體實現類(如 GregorianCalendar)實例。

核心實例創建

// 1. 當前時間(默認時區、默認 Locale)
Calendar cal = Calendar.getInstance();

// 2. 指定時區/ Locale
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT+8"), Locale.CHINA);

// 3. 從 Date 轉換
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());

// 4. 從毫秒數創建
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(System.currentTimeMillis());

設置指定日期時間

方式一:一次性設置年月日

Calendar cal = Calendar.getInstance();
// 注意:月份從 0 開始 (0=1月, 11=12月)
cal.set(2024, 2, 15); // 2024年3月15日

方式二:單獨設置字段

cal.set(Calendar.YEAR, 2024);
cal.set(Calendar.MONTH, 2);        // 3月
cal.set(Calendar.DATE, 15);        // 15號
cal.set(Calendar.HOUR_OF_DAY, 14); // 24制 14:00
cal.set(Calendar.MINUTE, 30);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);

常用字段常量

常量含義取值範圍
YEAR年份如 2024
MONTH月份0-11 (注意!)
DATE / DAY_OF_MONTH月份中的第幾天1-31
DAY_OF_WEEK星期幾1=周日, 2=周一...7=周六
DAY_OF_YEAR年份中的第幾天1-366
WEEK_OF_MONTH月份中的第幾周1-6
WEEK_OF_YEAR年份中的第幾周1-53
HOUR12制小時0-11
HOUR_OF_DAY24制小時0-23
MINUTE分鐘0-59
SECOND秒0-59
MILLISECOND毫秒0-999
AM_PM上午/下午0=AM, 1=PM

獲取日期時間信息

Calendar cal = Calendar.getInstance();

int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH) + 1; // +1 轉為人類可讀月份
int day = cal.get(Calendar.DATE);
int hour = cal.get(Calendar.HOUR_OF_DAY);
int minute = cal.get(Calendar.MINUTE);
int second = cal.get(Calendar.SECOND);
int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); // 1=周日

System.out.printf("%d-%02d-%02d %02d:%02d:%02d 星期%d%n", 
    year, month, day, hour, minute, second, dayOfWeek);

日期運算:add / roll 方法

add(field, amount) - 真實日期運算(推薦)

Calendar cal = Calendar.getInstance(); // 2024-01-31

// 向後推 1 個月 → 2024-02-29 (閏年自動處理)
cal.add(Calendar.MONTH, 1); 

// 向前推 100 天
cal.add(Calendar.DATE, -100);

// 加 2 年
cal.add(Calendar.YEAR, 2);

特點:會自動調整其他字段(如月份天數、進位借位),符合日曆邏輯。

roll(field, amount) - 單字段滾動(不進位)

Calendar cal = Calendar.getInstance();
cal.set(2024, 0, 31); // 1月31日

// 月份 +1,但不調整日期 → 2月31日 → 自動變為 2月29日(閏年) 或 2月28日
cal.add(Calendar.MONTH, 1);  // 正確:2月29日

// roll 不進位
cal.roll(Calendar.MONTH, 1); // 錯誤邏輯:嘗試設置 2月31日 → 內部處理可能異常

區別:add 是真實日期加減,roll 只改指定字段,不聯動其他字段(較少用)。

日期比較:before / after / compareTo


Calendar c1 = Calendar.getInstance();
c1.set(2024, 0, 1);  // 2024-01-01

Calendar c2 = Calendar.getInstance();
c2.set(2024, 11, 31); // 2024-12-31

// c2 在 c1 之後
boolean after = c2.after(c1);    // true
boolean before = c2.before(c1);  // false

// compareTo (Calendar 實現了 Comparable)
int cmp = c2.compareTo(c1); // 1 (c2 > c1)

Calendar 與 Date 互轉


// Calendar → Date
Date date = cal.getTime();

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

// Calendar ↔ 毫秒數
long millis = cal.getTimeInMillis();
cal.setTimeInMillis(millis);

實戰工具類封裝


public class CalendarUtils {
    
    /** 獲取當月第一天 00:00:00 */
    public static Calendar getMonthStart() {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.DAY_OF_MONTH, 1);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal;
    }
    
    /** 獲取當月最後一天 23:59:59.999 */
    public static Calendar getMonthEnd() {
        Calendar cal = getMonthStart();
        cal.add(Calendar.MONTH, 1);
        cal.add(Calendar.MILLISECOND, -1);
        return cal;
    }
    
    /** 判斷是否為今天 */
    public static boolean isToday(Calendar cal) {
        Calendar today = Calendar.getInstance();
        return cal.get(Calendar.YEAR) == today.get(Calendar.YEAR)
            && cal.get(Calendar.DAY_OF_YEAR) == today.get(Calendar.DAY_OF_YEAR);
    }
    
    /** 格式化輸出 */
    public static String format(Calendar cal, String pattern) {
        return new SimpleDateFormat(pattern).format(cal.getTime());
    }
}

避坑指南

坑點說明正確做法
月份 0-11MONTH=0 代表 1月設置/讀取時 ±1
星期 1=周日DAY_OF_WEEK: 1=周日轉換邏輯:(day+5)%7+1 → 1=周一
可變性Calendar 可變,set/add 修改原對象需副本時用 clone() 或新建實例
線程不安全SimpleDateFormat 非線程安全用 ThreadLocal 或 DateTimeFormatter (Java 8+)
lenient 模式默認寬容模式 (月份13→次年1月)嚴格模式:cal.setLenient(false)

Java 8+ 建議:java.time 包

新項目優先使用 java.time (JSR-310):

  • LocalDate、LocalTime、LocalDateTime - 不可變、線程安全
  • ZonedDateTime - 帶時區
  • DateTimeFormatter - 線程安全格式化
  • Period、Duration - 日期/時間間隔

// Java 8 等價代碼
LocalDateTime now = LocalDateTime.now();
LocalDateTime nextMonth = now.plusMonths(1);
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String str = nextMonth.format(fmt);

總結

Calendar 是 Java 日期時間處理的經典 API,核心掌握:月份 0-11、星期 1=周日、add 做日期運算、getTime/setTime 轉 Date、可變性注意副本。維護舊代碼必會,新項目強烈建議遷移至 java.time 獲得更安全、直觀的體驗。

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