在實際開發中,經常需要處理各種格式的日期字串,例如 2014-03-12 12:05:34、2014/3/12 12:5:34、2014年3月12日 13時5分34秒 甚至 13:05:34(僅時間)等。手動編寫大量 if-else 判斷不僅繁瑣,且難以維護。本文介紹一種基於正則表達式與 SimpleDateFormat 結合的通用日期解析工具類,能自動識別多種常見日期格式並統一轉換為標準格式 yyyy-MM-dd HH:mm:ss。
13:05:34)或「日.月」(如 21.12)等不完整資訊,自動補上當前日期或年份。-,再由 SimpleDateFormat 解析並格式化輸出。public class DateFormatUtil {
private static final Map<String, String> DATE_REG_FORMAT = new LinkedHashMap<>();
static {
// 帶完整時間的各種分隔符格式
DATE_REG_FORMAT.put("^\\d{4}\\D+\\d{1,2}\\D+\\d{1,2}\\D+\\d{1,2}\\D+\\d{1,2}\\D+\\d{1,2}\\D*$", "yyyy-MM-dd-HH-mm-ss");
DATE_REG_FORMAT.put("^\\d{4}\\D+\\d{2}\\D+\\d{2}\\D+\\d{2}\\D+\\d{2}$", "yyyy-MM-dd-HH-mm");
DATE_REG_FORMAT.put("^\\d{4}\\D+\\d{2}\\D+\\d{2}\\D+\\d{2}$", "yyyy-MM-dd-HH");
DATE_REG_FORMAT.put("^\\d{4}\\D+\\d{2}\\D+\\d{2}$", "yyyy-MM-dd");
DATE_REG_FORMAT.put("^\\d{4}\\D+\\d{2}$", "yyyy-MM");
DATE_REG_FORMAT.put("^\\d{4}$", "yyyy");
// 緊湊格式(無分隔符)
DATE_REG_FORMAT.put("^\\d{14}$", "yyyyMMddHHmmss");
DATE_REG_FORMAT.put("^\\d{12}$", "yyyyMMddHHmm");
DATE_REG_FORMAT.put("^\\d{10}$", "yyyyMMddHH");
DATE_REG_FORMAT.put("^\\d{8}$", "yyyyMMdd");
DATE_REG_FORMAT.put("^\\d{6}$", "yyyyMM");
// 僅時間:補當前日期
DATE_REG_FORMAT.put("^\\d{2}\\s*:\\s*\\d{2}\\s*:\\s*\\d{2}$", "yyyy-MM-dd-HH-mm-ss");
DATE_REG_FORMAT.put("^\\d{2}\\s*:\\s*\\d{2}$", "yyyy-MM-dd-HH-mm");
// 兩位年份或日.月格式
DATE_REG_FORMAT.put("^\\d{2}\\D+\\d{1,2}\\D+\\d{1,2}$", "yy-MM-dd");
DATE_REG_FORMAT.put("^\\d{1,2}\\D+\\d{1,2}$", "yyyy-dd-MM");
DATE_REG_FORMAT.put("^\\d{1,2}\\D+\\d{1,2}\\D+\\d{4}$", "dd-MM-yyyy");
}
public static String formatDate(String dateStr) {
String curDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
DateFormat targetFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for (Map.Entry<String, String> entry : DATE_REG_FORMAT.entrySet()) {
if (Pattern.compile(entry.getKey()).matcher(dateStr).matches()) {
DateFormat parser = new SimpleDateFormat(entry.getValue());
// 補全上下文邏輯
if (entry.getKey().contains("\\d{2}\\s*:\\s*\\d{2}")) {
dateStr = curDate + "-" + dateStr; // 僅時間 → 加上今天日期
} else if (entry.getKey().equals("^\\d{1,2}\\D+\\d{1,2}$")) {
dateStr = curDate.substring(0, 4) + "-" + dateStr; // 日.月 → 加上今年
}
// 統一分隔符並解析
String normalized = dateStr.replaceAll("\\D+", "-");
try {
return targetFormat.format(parser.parse(normalized));
} catch (ParseException e) {
throw new IllegalArgumentException("日期格式無效: " + dateStr, e);
}
}
}
throw new IllegalArgumentException("不支持的日期格式: " + dateStr);
}
}
主方法內置 20 組測試用例,涵蓋所有預定義格式,輸出均為標準 yyyy-MM-dd HH:mm:ss。例如:
2014年3月12日 13時5分34秒 → 2014-03-12 13:05:3413:05:34 → 2024-05-20 13:05:34(假設今天是 2024-05-20)21.12 → 2024-12-21 00:00:00LinkedHashMap 保持匹配優先級(如完整格式優於簡略格式)。ParseException 並轉為非受檢異常,簡化調用方處理。java.time 套件(DateTimeFormatter),線程安全且功能更豐富。該工具類通過「正則分派 + 格式補全 + 統一解析」三步走策略,優雅地解決了多格式日期解析難題,代碼結構清晰、易於擴展新格式,適合作為項目通用工具類引入。