如何在Node.js中使用celebrate的Joi验证字符串是否为有效日期?
Joi 校验日期字符串且保留字符串类型的实现方案
你可以通过以下两种方式实现需求,两种方案都不会将输入值转换为Date类型,完全保留原始字符串格式:
方案1:单字段自定义校验(适合少量使用场景)
直接在Joi.string()规则后追加自定义校验逻辑,示例代码如下:
const Joi = require('joi'); const validationSchema = Joi.object({ // 示例校验YYYY-MM-DD格式的合法日期字符串 targetDate: Joi.string() // 先校验格式匹配规则,可根据你的日期格式调整正则 .pattern(/^\d{4}-\d{2}-\d{2}$/) .custom((value, helpers) => { const parsedDate = new Date(value); // 避免Date自动修正不合法日期导致的误判,需和原始值比对 const formattedParsedDate = parsedDate.toISOString().split('T')[0]; if (parsedDate.toString() === 'Invalid Date' || formattedParsedDate !== value) { return helpers.message('请输入合法的YYYY-MM-DD格式日期'); } // 直接返回原始字符串,不会做类型转换 return value; }) .required() });
方案2:自定义Joi扩展(适合多字段复用场景)
如果多个位置都需要用到日期字符串校验,可以封装为Joi扩展全局复用:
const Joi = require('joi'); // 扩展Joi新增dateString类型 const customJoi = Joi.extend(joi => ({ type: 'dateString', base: joi.string(), messages: { 'dateString.invalid': '{{#label}} 为不合法的日期字符串' }, validate(value, helpers) { const parsedDate = new Date(value); const formattedParsedDate = parsedDate.toISOString().split('T')[0]; if (parsedDate.toString() === 'Invalid Date' || formattedParsedDate !== value) { return { value, errors: helpers.error('dateString.invalid') }; } return { value }; } })); // 使用扩展后的类型 const validationSchema = customJoi.object({ targetDate: customJoi.dateString().required(), anotherDate: customJoi.dateString().required() });
注意事项
- 若需校验带时间的日期格式(如YYYY-MM-DD HH:mm:ss),仅需调整正则匹配规则,以及Date转字符串后和原始值的比对逻辑即可。
- 不要仅通过
new Date(value).toString() === 'Invalid Date'判断合法性,Date对象会自动修正异常日期(如2023-02-30会被转为2023-03-02),不做原始值比对会出现校验误判。
内容的提问来源于stack exchange,提问作者Smiti Goel
相关产品推荐
相关产品推荐

