
本文介绍如何使用 `java.time` 包中的 `datetimeformatter` 灵活解析并统一格式化不同结构的日期时间字符串(如 "12-1-2012 t 10:23:34" 和 "20-10-2012 t 10:34:22"),避免过时且线程不安全的 `simpledateformat`。
在 Java 中处理多格式日期输入时,关键在于分离解析(parsing)与格式化(formatting)逻辑。原始代码中试图用单一 SimpleDateFormat("dd-MM-yyyy T HH:mm:ss") 同时匹配 "12-1-2012"(单数字月/日)和 "20-10-2012"(双数字月/日),这必然失败——因为 dd 和 MM 要求两位补零,而 "12-1-2012" 中的 1 不满足 MM 的严格匹配。
现代解决方案是采用 java.time API(Java 8+),它提供线程安全、不可变且语义清晰的 DateTimeFormatter。核心思路是:
✅ 使用宽松模式解析:用 d-M-uuuu 'T' HH:mm:ss ——
d(日)和 M(月)支持 1~31 / 1~12 的单/多位输入;
uuuu 表示四位年份(推荐替代 yyyy,对“周历年”更鲁棒);
'T' 是字面量引号,确保空格与字母 T 精确匹配。✅ 使用严格模式格式化:用 dd-MM-uuuu 'T' HH:mm:ss ——
输出始终为两位补零的 dd 和 MM,达成统一目标格式。
以下是完整可运行示例:
立即学习“Java免费学习笔记(深入)”;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class DateTimeMultiFormat {
public static void main(String[] args) {
// 解析器:容忍单/双位日、月
DateTimeFormatter parser = DateTimeFormatter.ofPattern("d-M-uuuu 'T' HH:mm:ss", Locale.ENGLISH);
// 格式化器:强制输出两位补零
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-uuuu 'T' HH:mm:ss", Locale.ENGLISH);
String[] inputs = { "12-1-2012 T 10:23:34", "20-10-2012 T 10:34:22" };
for (String input : inputs) {
LocalDateTime parsed = LocalDateTime.parse(input, parser);
String normalized = parsed.format(formatter);
System.out.println(normalized); // 输出:12-01-2012 T 10:23:34 / 20-10-2012 T 10:34:22
}
}
}⚠️ 注意事项:
- 勿混用 y 与 u:u(year of era)在跨世纪或特殊日历场景下比 y(year)更可靠,尤其涉及 WeekFields 或时区计算时;
- 显式指定 Locale:避免因 JVM 默认区域设置导致解析失败(如月份缩写);
- 异常处理:生产环境应包裹 try-catch (DateTimeParseException e) 并提供有意义的错误提示;
- 性能优化:DateTimeFormatter 是线程安全的,建议声明为 static final 复用,而非每次创建。
总结:摒弃 SimpleDateFormat,拥抱 java.time —— 通过组合多个专用 DateTimeFormatter 实例,即可优雅、健壮、高效地应对多格式日期输入场景。










