Java 8 的 java.time API 自定义解析核心是组合扩展标准 DateTimeFormatter,而非重写逻辑,适用于模糊日期、非标标记、多格式容错等场景;可通过 DateTimeFormatterBuilder 构建带字面量、可选字段、大小写不敏感的解析器,或封装多 pattern 容错逻辑,相对语义需预处理,TemporalQuery 仅用于极少数深度定制。

Java 8 引入的 java.time API(如 LocalDateTime、ZonedDateTime)默认通过 DateTimeFormatter 解析字符串。自定义解析器的核心不是“重写解析逻辑”,而是**组合或扩展标准 formatter 的行为**,解决标准格式不覆盖的场景(如模糊日期、带非标准标记的字符串、多格式容错等)。
用 DateTimeFormatter.ofPattern() + 自定义符号
当需要解析含特殊占位符或非标准分隔符的字符串时,可自定义模式,并配合 DateTimeFormatterBuilder 注册替换规则:
- 使用
DateTimeFormatterBuilder构建 formatter,支持宽松解析(如忽略空格、允许省略前导零) - 用
parseCaseInsensitive()支持大小写不敏感(如 "Jan"/"JAN") - 用
optionalStart()和optionalEnd()处理可选字段(如带或不带秒的 ISO 格式) - 用
appendText()或appendLiteral()显式匹配固定文本(如解析"2024-05-20@14:30"中的@)
示例:解析形如 "2024/05/20@14:30:05.123" 的字符串
DateTimeFormatter custom = new DateTimeFormatterBuilder()
.appendPattern("yyyy/MM/dd")
.appendLiteral('@')
.appendPattern("HH:mm:ss.SSS")
.toFormatter();
LocalDateTime dt = LocalDateTime.parse("2024/05/20@14:30:05.123", custom);
处理多格式兼容(一个字符串多种可能)
标准 DateTimeFormatter 不支持“尝试多个 pattern”,需手动封装容错逻辑:
立即学习“Java免费学习笔记(深入)”;
将后端 Java 接口文档转换为前端 TypeScript 类型定义(interface / type)。输入:飞书文档、Spring Boot 接口文档、Swagger/OpenAPI、手写 API 文档等。输出:包含请求参数与响应结果的 .md 文件,含完整 JSDoc 注释。触发关键词:Java 转 TS、接口转换、生成前端类型、接口文档转 TypeScript、DTO/VO/BO 转 interface、后端文档转前端类型、生成接口类型、类型定义生成。
- 准备一组预定义的 formatter(如
ISO_LOCAL_DATE_TIME、ofPattern("yyyy-MM-dd HH:mm")、自定义中文格式等) - 遍历尝试解析,捕获
DateTimeParseException,跳过失败项 - 返回首个成功解析的结果(注意时区和类型一致性,避免混用
LocalDateTime和ZonedDateTime)
示例:支持两种常见格式
List<DateTimeFormatter> formatters = List.of(
DateTimeFormatter.ISO_LOCAL_DATE_TIME,
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"),
DateTimeFormatter.ofPattern("yyyyMMddHHmmss")
);
public static LocalDateTime parseMultiFormat(String text) {
for (DateTimeFormatter f : formatters) {
try {
return LocalDateTime.parse(text, f);
} catch (DateTimeParseException ignored) {}
}
throw new IllegalArgumentException("无法解析日期时间: " + text);
}
解析含业务语义的字符串(如“今天”、“上周三”)
这类非标准表达需**先做文本预处理,再转为标准时间点**,不属于 DateTimeFormatter 职责范围:
- 用正则或关键词匹配识别相对表达(如 "今天" →
LocalDate.now(),"明天" →LocalDate.now().plusDays(1)) - 对含“第X周”“上月”等复杂语义,建议引入轻量库(如
Time4J)或自行构建解析规则树 - 解析后统一转为
LocalDateTime或ZonedDateTime,再参与后续计算
示例:“今天 14:30” → 当前日期 + 指定时间
public static LocalDateTime parseRelative(String text) {
LocalDate today = LocalDate.now();
if (text.startsWith("今天 ")) {
String timePart = text.substring(3).trim();
LocalTime time = LocalTime.parse(timePart, DateTimeFormatter.ofPattern("HH:mm"));
return LocalDateTime.of(today, time);
}
// 其他规则...
throw new IllegalArgumentException("不支持的相对表达: " + text);
}
自定义 TemporalQuery(高级:控制解析细节)
极少数场景需干预解析过程本身(如把缺失的年份默认设为当前年、自动补全两位年份为四位),可通过实现 TemporalQuery<t></t> 并结合 DateTimeFormatter.withResolverFields() 或 withResolverStyle() 配合使用:
- 通常只需设置
ResolverStyle.STRICT/LENIENT/SMART控制校验严格度 - 真正需
TemporalQuery的情况极少(如解析 “05/20” 默认补当年),更推荐在 parse 后做后处理 - 不建议直接操作
TemporalAccessor字段映射,易出错且可读性差
不复杂但容易忽略

















