日期時間處理是業務開發的高頻痛點:月份天數不規則、閏年計算、週末判斷、多格式輸出。JDK 1.1 引入 Calendar、SimpleDateFormat 奠定了 Java 日期處理基石(JDK 8+ 建議用 java.time)。本文以 JSP 為載體,系統講解核心 API 與常見業務場景代碼模式。
<%@ page import="java.util.Calendar, java.text.SimpleDateFormat" pageEncoding="UTF-8" %>
| 類 | 核心方法 | 說明 |
|---|---|---|
| Calendar | getInstance() | 獲取當前時區/語言環境的實例 |
clear() | 重置所有字段,避免殘留值干擾 | |
set(y, m, d) | 設置年、月(0-11)、日,月份從0開始 | |
get(field) | 獲取字段值:DAY_OF_WEEK(1=周日...7=周六)、DATE/DAY_OF_MONTH、WEEK_OF_MONTH 等 | |
add(field, amount) | 字段加減,自動進位(如月份溢出) | |
getActualMaximum(DATE) | 獲取當月實際天數(自動處理閏年) | |
getTime() | 轉為 Date 對象,供格式化使用 | |
| SimpleDateFormat | new SimpleDateFormat(pattern) | 模式字母:y年 M月 d日 H時(24) m分 s秒 S毫秒 E星期 D年間天數 w年間周數 W月內周數 |
format(Date) | 日期→字符串 | |
parse(String) | 字符串→日期(拋 ParseException) |
"yyyy-MM-dd" → 2024-03-15
"yyyy年MM月dd日" → 2024年03月15日
"yyyy-MM-dd HH:mm:ss" → 2024-03-15 14:30:05
"EEE, MMM d, yyyy" → Fri, Mar 15, 2024 (需 Locale.ENGLISH)
"yyyy-MM-dd'T'HH:mm:ssXXX" → 2024-03-15T14:30:05+08:00 (ISO 8601)
<%
int y = 2024, m = 2, d = 1; // 默認值
try {
y = Integer.parseInt(request.getParameter("year"));
m = Integer.parseInt(request.getParameter("month")) - 1; // 前端1-12 → Calendar 0-11
d = Integer.parseInt(request.getParameter("day"));
} catch (Exception ignored) {}
Calendar cal = Calendar.getInstance();
cal.clear();
cal.set(y, m, d);
%>
<%
String[] weekNames = {"", "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
int dow = cal.get(Calendar.DAY_OF_WEEK); // 1=周日 ... 7=周六
boolean isWeekend = (dow == 1 || dow == 7);
%>
今天是:<%= weekNames[dow] %> <%= isWeekend ? "(週末)" : "(工作日)" %>
<%
Calendar workCal = (Calendar) cal.clone();
workCal.set(Calendar.DATE, 1); // 當月1號
int maxDay = workCal.getActualMaximum(Calendar.DATE);
int workDays = 0;
for (int i = 1; i <= maxDay; i++) {
workCal.set(Calendar.DATE, i);
int dow = workCal.get(Calendar.DAY_OF_WEEK);
if (dow != 1 && dow != 7) workDays++; // 排除周六日
}
%>
<%= workCal.get(Calendar.YEAR) %>年<%= workCal.get(Calendar.MONTH)+1 %>月共有 <%= maxDay %> 天,工作日 <%= workDays %> 天。
<%!
public String formatDate(Calendar c, String pattern) {
if (c == null) return "";
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
return sdf.format(c.getTime());
}
%>
<!-- 使用 -->
完整日期:<%= formatDate(cal, "yyyy年MM月dd日 EEEE") %>
ISO格式:<%= formatDate(cal, "yyyy-MM-dd'T'HH:mm:ssXXX") %>
Calendar.JANUARY = 0,前端傳 1-12 需 -1SimpleDateFormat 非線程安全,不要定為 static/實例變量,每次用 new 或用 ThreadLocalLocalDate、LocalDateTime、DateTimeFormatter、ZoneId,不可變、線程安全、API 更清晰Calendar + SimpleDateFormat 是 Java 日期處理的「經典雙子星」。掌握 clear()-set()-get()-add() 鏈式操作與模式字母,能應對 95% 業務場景。但請牢記:新項目首選 java.time,舊項目維護時做好線程安全防護,避免格式化器共享導致的詭異 Bug。