Java中Apache Commons GenericValidator.isDate支持的日期格式及校验问题
问题根因
不是GenericValidator.isDate不支持该日期格式,问题出在两个地方:
- 模式写法不规范:你把代表UTC时区的
Z用单引号包裹成了固定字面量,相当于告诉解析器这个位置的Z是无意义的普通字符,不需要按时区解析,本身违背了ISO 8601日期的语义。 - 版本bug触发校验失败:旧版本Apache Commons Validator的
isDate方法存在实现缺陷,统计模式匹配长度时不会排除单引号转义符,你写的模式里包含'T'、'Z'两处转义内容,方法会误判模式长度和输入字符串长度不匹配,直接返回false。就算绕过长度校验,因为方法默认用JVM时区构建解析器,在非UTC时区环境下,严格模式要求「解析后再格式化的字符串和原输入完全一致」,时区偏差也会导致比对失败。
修复方案
推荐直接把模式改成不需要额外转义Z的写法,兼容Java 7及以上版本,同时规避转义符导致的长度计算bug:
String createdAt = "2022-06-08T21:11:31.710Z"; assertTrue(GenericValidator.isDate(createdAt, "yyyy-MM-dd'T'HH:mm:ss.SSSX", true));
模式里的X是ISO 8601时区匹配符,可以自动识别结尾代表UTC的Z字符,不需要加单引号转义。
如果需要兼容Java 6及更老版本,不要直接用GenericValidator.isDate,手动构建SimpleDateFormat时指定UTC时区,再做解析校验更可靠。
该方法支持的日期格式
GenericValidator.isDate底层完全依赖JDK自带的java.text.SimpleDateFormat实现解析,所有符合SimpleDateFormat模式规则的格式都支持,常用模式符如下:
yyyy:4位年份MM:2位月份(01-12)dd:2位日期(01-31)HH:24小时制小时(00-23)mm:分钟(00-59)ss:秒(00-59)SSS:毫秒(000-999)X:ISO 8601时区(Java 7+支持,可匹配Z、+08:00、-05:00等格式)z:通用时区标识(比如CST、GMT+8)
注意:这个方法默认取JVM当前时区做解析,校验带时区的跨环境日期时很容易出现偏差,生产环境使用建议明确指定时区后再做解析。
内容的提问来源于stack exchange,提问作者Kosh
相关产品推荐
相关产品推荐

