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

Spring Boot如何接收阿拉伯数字格式的日期查询参数?

Spring Boot 解析阿拉伯数字格式日期查询参数

问题场景

需要在Spring Boot应用中接收阿拉伯-Indic数字格式的日期作为查询参数(例如٢٠٢١-٠٧-٢٠对应英文日期2021-07-20),已实现单独解析该格式的代码,但使用@DateTimeFormat(pattern = "yyyy-MM-dd")绑定LocalDate参数时,会抛出类型转换错误:

org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'dateRange' on field 'fromDate': rejected value [٢٠٢١-٠٧-٢٠];
codes [typeMismatch.dateRange.fromDate,typeMismatch.fromDate,typeMismatch.java.time.LocalDate,typeMismatch];
arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [dateRange.fromDate,fromDate];
arguments [];
default message [fromDate]];
default message [Failed to convert value of type 'java.lang.String[]' to required type 'java.time.LocalDate';
nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@org.springframework.format.annotation.DateTimeFormat java.time.LocalDate] for value '٢٠٢١-٠٧-٢٠'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [٢٠٢١-٠٧-٢٠]]

解决方案

通过自定义LocalDate转换器并注册到Spring的转换体系中,替换默认的日期解析逻辑,同时兼容阿拉伯数字格式和普通数字格式的日期。

1. 实现自定义日期转换器

创建Converter<String, LocalDate>实现类,集成阿拉伯数字日期解析逻辑,同时保留默认ISO格式的兼容:

import org.springframework.core.convert.converter.Converter;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DecimalStyle;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;

public class ArabicLocalDateConverter implements Converter<String, LocalDate> {

    private final DateTimeFormatter arabicDateFormatter;
    private final DateTimeFormatter defaultDateFormatter;

    public ArabicLocalDateConverter() {
        // 初始化阿拉伯-Indic数字格式的日期解析器
        DecimalStyle defaultDecimalStyle = DateTimeFormatter.ISO_LOCAL_DATE.getDecimalStyle();
        this.arabicDateFormatter = DateTimeFormatter.ISO_LOCAL_DATE
                .withDecimalStyle(defaultDecimalStyle.withZeroDigit('\u0660'));
        // 保留默认ISO日期格式解析,兼容普通数字日期
        this.defaultDateFormatter = DateTimeFormatter.ISO_LOCAL_DATE;
    }

    @Override
    public LocalDate convert(String source) {
        try {
            // 解码URL编码的日期字符串(处理前端传递的编码参数)
            String decodedSource = URLDecoder.decode(source, StandardCharsets.UTF_8);
            // 优先尝试阿拉伯数字格式解析
            return LocalDate.parse(decodedSource, arabicDateFormatter);
        } catch (Exception arabicParseEx) {
            // 阿拉伯格式解析失败,尝试默认ISO格式
            try {
                return LocalDate.parse(source, defaultDateFormatter);
            } catch (Exception defaultParseEx) {
                throw new IllegalArgumentException("无法解析日期参数:" + source, defaultParseEx);
            }
        }
    }
}

2. 注册自定义转换器

通过WebMvcConfigurer配置类,将自定义转换器添加到Spring的格式化注册表中:

import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addFormatters(FormatterRegistry registry) {
        // 注册自定义LocalDate转换器,覆盖默认转换逻辑
        registry.addConverter(new ArabicLocalDateConverter());
    }
}

3. 调整参数绑定方式

在接口参数中直接使用LocalDate类型,无需再添加@DateTimeFormat注解,转换器会自动处理两种格式的日期:

// 示例Controller方法
@GetMapping("/query")
public ResponseEntity<String> queryByDateRange(@RequestParam LocalDate fromDate) {
    // 业务逻辑处理
    return ResponseEntity.ok("解析后的日期:" + fromDate);
}

原理说明

Spring默认的LocalDate转换器依赖系统默认的DecimalStyle,仅支持ASCII数字(0-9)。自定义转换器通过指定阿拉伯-Indic数字的零字符(\u0660),修改DateTimeFormatter的数字解析规则,从而支持阿拉伯数字格式的日期解析,同时兼容原有普通日期格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 17:15:58