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

Java String 轉 Date 完整指南:SimpleDateFormat 雙重格式化技巧與線程安全最佳實踐

     編輯:Java 程式設計入門

核心場景

前端/JSON 傳遞日期字符串(如 "2012-08-25"),後端需解析為 Date 對象,或轉換為其他格式字符串(如 "2012年8月25日")用於展示/存儲。

雙重格式化標準範式

String input = "2012-08-25";
// 1. 解析器:匹配輸入格式
SimpleDateFormat parser = new SimpleDateFormat("yyyy-MM-dd");
// 2. 格式化器:輸出目標格式
SimpleDateFormat formatter = new SimpleDateFormat("yyyy年M月d日");

try {
    Date date = parser.parse(input);        // String → Date
    String output = formatter.format(date); // Date → String
    System.out.println(output); // 2012年8月25日
} catch (ParseException e) {
    e.printStackTrace();
}

常見格式模式對照表

模式字母含義示例
y年2012 / 12
M月08 / 8 / Aug
d日25 / 5
H時(24制)14 / 2
m分05 / 5
s秒09 / 9
S毫秒123
E星期週六
aAM/PMPM
Z時區偏移+0800

實戰示例

斜杠分隔格式

String str = "2012/08/25";
SimpleDateFormat p = new SimpleDateFormat("yyyy/MM/dd");
SimpleDateFormat f = new SimpleDateFormat("yyyy年MM月dd日");
System.out.println(f.format(p.parse(str))); // 2012年08月25日

帶時間格式

String dt = "2023-10-01 14:30:45";
SimpleDateFormat p = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat f = new SimpleDateFormat("yyyy/MM/dd HH:mm");
System.out.println(f.format(p.parse(dt))); // 2023/10/01 14:30

⚠ 線程安全陷阱與解決方案

SimpleDateFormat 非線程安全,多線程共用實例會導致解析錯誤或數據競爭。

方案一:ThreadLocal 隔離(推薦 Java 7/8)

private static final ThreadLocal<SimpleDateFormat> TL_PARSER =
    ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));

public static Date parse(String s) throws ParseException {
    return TL_PARSER.get().parse(s);
}

方案二:局部變量每次新建(低併發場景)

public static Date parse(String s) throws ParseException {
    return new SimpleDateFormat("yyyy-MM-dd").parse(s); // 無共享,安全
}

方案三:Java 8+ java.time 包(現代最佳實踐)

// 解析
LocalDate date = LocalDate.parse("2012-08-25", DateTimeFormatter.ISO_LOCAL_DATE);
// 格式化
String out = date.format(DateTimeFormatter.ofPattern("yyyy年M月d日"));
// 與 Date 互轉
Date d = Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant());
LocalDate ld = d.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
  • DateTimeFormatter 不可變且線程安全,可靜態常量複用;
  • API 更清晰,LocalDate/LocalDateTime/Instant 語義明確。

總結建議

  1. 新項目優先使用 java.time,拋棄 SimpleDateFormat;
  2. 維護舊代碼時,用 ThreadLocal 或局部新建保證線程安全;
  3. 格式模式常量化,避免魔術字符串分散;
  4. 異常處理:捕獲 ParseException 並轉換為業務異常,提供友好提示。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved