You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

日期字符串解析失败求助:如何正确格式化编码日期参数?

问题分析与解决方案

错误原因

日期解析失败有两个核心问题:

  1. URL编码未处理:传入的字符串2022-10-30T13%3A28%3A41.530530中的%3A是URL编码后的冒号(:),直接解析会因字符不匹配报错。
  2. 格式器不匹配:代码中使用的yyyy-MM-dd HH:mm:ss格式,与实际传入的yyyy-MM-dd'T'HH:mm:ss.SSSSSS格式(带T分隔符、毫秒数)完全不兼容。

另外,你添加的@JsonFormat注解无效,因为该注解仅作用于JSON请求体的字段反序列化,而你的日期参数是URL请求参数,不受Jackson的JSON解析规则管控。

修复步骤

1. 先对日期字符串做URL解码

使用URLDecoder将编码后的字符还原为原始格式:

import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;

// 解码示例
String decodedStart = URLDecoder.decode(params.getStart(), StandardCharsets.UTF_8);
// 解码后得到:2022-10-30T13:28:41.530530

2. 使用匹配的日期格式器解析

由于解码后的字符串符合ISO-8601标准格式,直接使用JDK内置的ISO_LOCAL_DATE_TIME格式器即可,无需自定义格式:

import java.time.format.DateTimeFormatter;

// 替换原有的DateTimeFormatter定义
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;

或者如果需要明确指定毫秒位数的自定义格式,也可以使用:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSS");

修改后的完整代码

default Specification<View> getSpecificationByParams(StatsSearchParams params) {
    return (((root, query, criteriaBuilder) -> {
        List<Predicate> predicates = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;

        if (params.getUris() != null) {
            for (String uri : params.getUris()) {
                predicates.add(criteriaBuilder.in(root.get("uri")).value(uri));
            }
        }
        if (params.getStart() != null) {
            // 先解码再解析
            String decodedStart = URLDecoder.decode(params.getStart(), StandardCharsets.UTF_8);
            predicates.add(criteriaBuilder.greaterThan(
                    root.get("timestamp"),
                    LocalDateTime.parse(decodedStart, formatter)));
        }
        if (params.getEnd() != null) {
            // 先解码再解析
            String decodedEnd = URLDecoder.decode(params.getEnd(), StandardCharsets.UTF_8);
            predicates.add(criteriaBuilder.lessThanOrEqualTo(
                    root.get("timestamp"),
                    LocalDateTime.parse(decodedEnd, formatter)));
        }

        return criteriaBuilder.and(predicates.toArray(Predicate[]::new));
    }));
}

额外优化建议

如果你的统计服务是通过Spring MVC接收请求参数,也可以在StatsSearchParams类的日期字段上使用@DateTimeFormat注解,让框架自动完成解码和格式转换:

public class StatsSearchParams {
    // 其他字段...

    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
    private LocalDateTime start;

    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
    private LocalDateTime end;

    // getter/setter...
}

这种情况下,你可以直接在Specification中使用params.getStart()和params.getEnd(),无需手动解码和解析,代码会更简洁。

内容的提问来源于stack exchange,提问作者Arm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 23:10:53