如何在Yup中校验日期是否符合指定格式?
问题:用Yup校验日期时如何强制指定格式?
我现在用Yup校验日期输入字段,代码如下:
const dateToCheck = yup .date() .nullable() .transform((curr, orig) => (orig === '' ? null : curr)) .required() .min(minDate, 'Date cannot be this early') .max(maxDate, 'Date too much in the future') .test('format', 'Date is invalid', date => (date?.getFullYear() ?? 0) <= 9999)
现在的问题是,Yup的date()方法会自动识别多种格式(比如01.01.2000和2000/01/01都能通过校验),但我需要仅允许特定格式通过——要么只接受dd.MM.yyyy,要么只接受yyyy/MM/dd,其他格式都标记为无效。请问在Yup里怎么实现这个需求?
解决方案
核心思路是:不要依赖Yup自动解析日期,而是先通过正则校验原始输入字符串的格式,再手动将其转换为合法的Date对象(格式不匹配时返回无效值)。
情况1:强制要求dd.MM.yyyy格式
修改校验规则,加入正则校验和自定义转换逻辑:
const dateToCheck = yup .string() // 先将字段视为字符串,方便直接校验原始格式 .nullable() .transform((curr, orig) => orig === '' ? null : curr) .required('Date is required') // 第一步:用正则匹配dd.MM.yyyy格式 .matches(/^\d{2}\.\d{2}\.\d{4}$/, 'Date must be in dd.MM.yyyy format') // 第二步:验证日期实际合法性(比如排除2月30号这类格式正确但逻辑错误的日期) .test('valid-date', 'Invalid date', value => { if (!value) return true; const [day, month, year] = value.split('.').map(Number); const date = new Date(year, month - 1, day); // 确保转换后的日期与原始输入的日/月/年完全匹配 return date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day; }) // 第三步:将合法字符串转换为Date对象,供后续min/max校验使用 .transform((value) => { if (!value) return null; const [day, month, year] = value.split('.').map(Number); return new Date(year, month - 1, day); }) .min(minDate, 'Date cannot be this early') .max(maxDate, 'Date too much in the future');
情况2:强制要求yyyy/MM/dd格式
调整正则和转换逻辑即可:
const dateToCheck = yup .string() .nullable() .transform((curr, orig) => orig === '' ? null : curr) .required('Date is required') .matches(/^\d{4}\/\d{2}\/\d{2}$/, 'Date must be in yyyy/MM/dd format') .test('valid-date', 'Invalid date', value => { if (!value) return true; const [year, month, day] = value.split('/').map(Number); const date = new Date(year, month - 1, day); return date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day; }) .transform((value) => { if (!value) return null; const [year, month, day] = value.split('/').map(Number); return new Date(year, month - 1, day); }) .min(minDate, 'Date cannot be this early') .max(maxDate, 'Date too much in the future');
关键说明
- 将字段从
date()改为string(),直接校验原始输入的格式,避免Yup自动兼容多种日期字符串。 matches()方法用来做格式的正则校验,直接返回格式错误提示。- 额外的
test()方法用于过滤格式正确但实际无效的日期。 - 最后通过
transform()将合法字符串转为Date对象,保证后续的min()/max()校验能正常运行。
内容的提问来源于stack exchange,提问作者Alex T
相关产品推荐
相关产品推荐

