資料庫日期型別對應
| SQL 型別 | Java 型別 | 精度 | 適用場景 |
| DATE | java.sql.Date | 年月日 | 生日、入職日期 |
| TIME | java.sql.Time | 時分秒 | 打卡時間、排程時間 |
| DATETIME / TIMESTAMP | java.sql.Timestamp | 年月日時分秒.納秒 | 訂單建立時間、日誌記錄 |
核心 API 操作範例
// 查詢 DATETIME 欄位
ResultSet rs = stmt.executeQuery("SELECT datetime FROM time_table");
while (rs.next()) {
// 方式 1:分別取得 Date + Time 再格式化
Date d = rs.getDate("datetime");
Time t = rs.getTime("datetime");
SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月dd日");
SimpleDateFormat tf = new SimpleDateFormat("HH時mm分ss秒");
System.out.println(df.format(d) + tf.format(t));
// 方式 2:直接取得 Timestamp(推薦)
Timestamp ts = rs.getTimestamp("datetime");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH時mm分ss秒");
System.out.println(sdf.format(ts));
// 方式 3:提取月份等單一欄位
Calendar cal = Calendar.getInstance();
cal.setTime(ts);
int month = cal.get(Calendar.MONTH) + 1; // 0-based
}
資料寫入最佳實踐
// 使用 PreparedStatement 避免 SQL 注入與格式問題
String sql = "INSERT INTO events (event_time) VALUES (?)";
PreparedStatement ps = conn.prepareStatement(sql);
// 寫入 Timestamp(含納秒)
ps.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
// 或寫入 Date(僅日期)
ps.setDate(1, new java.sql.Date(System.currentTimeMillis()));
// 或寫入 Time(僅時間)
ps.setTime(1, new java.sql.Time(System.currentTimeMillis()));
ps.executeUpdate();
常見陷阱與解決方案
- java.util.Date vs java.sql.Date:
java.sql.Date 繼承自 java.util.Date,但 toString() 僅輸出日期部分。轉換:new java.sql.Date(utilDate.getTime())
- 時區問題:資料庫儲存 UTC,應用層轉換使用者時區。使用
Calendar 或 Java 8 ZonedDateTime 處理。
- 格式化執行緒不安全:
SimpleDateFormat 非執行緒安全,請使用 ThreadLocal 或 Java 8 DateTimeFormatter(不可變、執行緒安全)。
- MySQL zero-date:
0000-00-00 會導致例外,連線字串加 zeroDateTimeBehavior=convertToNull。
Java 8+ 現代化寫法
// ResultSet 直接取得 LocalDateTime (JDBC 4.2+)
LocalDateTime ldt = rs.getObject("datetime", LocalDateTime.class);
// 格式化
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH時mm分ss秒");
System.out.println(ldt.format(fmt));
// 寫入
ps.setObject(1, LocalDateTime.now());