Java 時間處理經歷了三代 API 演進:Date/Calendar(1.0/1.1,缺陷多)、SimpleDateFormat(格式化)、java.time(Java 8+,不可變、線程安全、領域清晰)。本文提供各版本最佳實踐代碼模板與避坑指南。
import java.time.*;
import java.time.format.DateTimeFormatter;
// 1. 當前瞬間(UTC)
Instant nowInstant = Instant.now(); // 2024-01-15T06:30:00.123Z
// 2. 當前本地日期時間(無時區)
LocalDateTime nowLocal = LocalDateTime.now(); // 2024-01-15T14:30:00.123
// 3. 當前時區日期時間(推薦業務使用)
ZonedDateTime nowZoned = ZonedDateTime.now(); // 2024-01-15T14:30:00.123+08:00[Asia/Shanghai]
// 4. 格式化輸出
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formatted = nowZoned.format(fmt); // "2024-01-15 14:30:00"
// 5. 解析字符串
LocalDateTime parsed = LocalDateTime.parse("2024-01-15 14:30:00", fmt);
// 6. 日期運算
LocalDateTime tomorrow = nowLocal.plusDays(1);
LocalDateTime lastMonth = nowLocal.minusMonths(1);
Period period = Period.between(LocalDate.now(), LocalDate.of(2025, 1, 1));
// 7. 時區轉換
ZonedDateTime nyTime = nowZoned.withZoneSameInstant(ZoneId.of("America/New_York"));
// 8. 時間戳互轉
long epochMilli = nowInstant.toEpochMilli();
Instant fromMilli = Instant.ofEpochMilli(epochMilli);
| 類 | 含義 | 是否含時區 | 適用場景 |
|---|---|---|---|
Instant | 時間線上的瞬間 | UTC | 日誌時間戳、跨系統傳輸、持久化 |
LocalDateTime | 本地日期時間 | 無 | 業務邏輯計算、表單綁定 |
ZonedDateTime | 帶時區日期時間 | 有 | 用戶顯示、定時任務、國際化 |
LocalDate | 本地日期 | 無 | 生日、證件到期、報表日期 |
LocalTime | 本地時間 | 無 | 鬧鐘、營業時間 |
import java.util.Date;
import java.text.SimpleDateFormat;
Date now = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str = sdf.format(now); // "2024-01-15 14:30:00"
System.out.println("Today is " + str);
import java.util.Calendar;
Calendar cal = Calendar.getInstance(); // 當前時間
cal.add(Calendar.DAY_OF_MONTH, 1); // 明天
cal.add(Calendar.MONTH, -1); // 上個月
cal.set(Calendar.HOUR_OF_DAY, 0); // 設置為當天 00:00:00
Date date = cal.getTime(); // 轉回 Date
SimpleDateFormat 非線程安全,多線程共用實例會導致解析錯誤/數據竄改。new SimpleDateFormat(...) 每次新建。ThreadLocal<SimpleDateFormat> 緩存複用。FastDateFormat(線程安全)。<%@ page import="java.time.*, java.time.format.*" %>
<%
ZonedDateTime now = ZonedDateTime.now();
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
%>
當前時間:<%= now.format(fmt) %>
function printDate() {
var today = new Date();
var day = String(today.getDate()).padStart(2, '0');
var month = String(today.getMonth() + 1).padStart(2, '0'); // 月份 0-11
var year = today.getFullYear();
document.getElementById('intoDate').value = year + '-' + month + '-' + day;
}
// 頁面加載自動調用
window.onload = printDate;
| 符號 | 含義 | 示例 |
|---|---|---|
yyyy | 年(4位) | 2024 |
MM | 月(01-12) | 01 |
dd | 日(01-31) | 15 |
HH | 時(00-23,24制) | 14 |
mm | 分(00-59) | 30 |
ss | 秒(00-59) | 00 |
SSS | 毫秒(000-999) | 123 |
zzz | 時區偏移 | +0800 |
plusDays vs add)。TIMESTAMP WITH TIME ZONE 或 BIGINT 存毫秒數。LocalDateTime + JPA @Convert 或 Hibernate 內置 JavaTime 類型。ZoneId。時間處理是業務系統的「隱形基礎設施」,選對 API、統一時區、正確格式化,能消除 99% 的時間相關 Bug。Java 8 java.time 是 JSR-310 專家組(含 Joda-Time 作者 Stephen Colebourne)精心設計的現代標準,請毫不猶豫地全面遷移。