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

DD-MON-YY格式JS正则日期验证:31日判定错误求助

DD-MON-YY日期验证错误:3月、5月31日被误判无效

我多年来一直受此问题困扰,如今终于无法忍受。使用以下JS正则验证DD-MON-YY格式日期时,会错误判定3月(Mar)、5月(May)的31日为无效日期,但这两个月份实际都有31天。我反复检查正则却找不到问题根源,希望能得到他人协助排查。

原验证代码

function isdateField1(currVal) {
 if (currVal == '') return false;

//Declare Regex  
var rxDatePattern = /^(\d{1,2})(-)(?:|(jan)|(feb)|(mar)|(apr)|(may)|(jun)|(jul)|(aug)|(sep)|(oct)|(nov)|(dec))(-)(\d{2})$/i;

var dtArray = currVal.match(rxDatePattern);

if (dtArray == null) return false;

var dtDay = parseInt(dtArray[1]);
var dtMonth = parseInt(dtArray[3]);
var dtYear = parseInt(dtArray[17]);

if (isNaN(dtMonth)) {
    for (var i = 4; i <= 15; i++) {
        if ((dtArray[i])) {
            dtMonth = i - 3;
            break;
        }
    }
}
if (dtMonth < 1 || dtMonth > 12) return false;
else if (dtDay < 1 || dtDay > 31) return false;
else if ((dtMonth == 4 || dtMonth == 6 || dtMonth == 9 || dtMonth == 11) && dtDay == 31) return false;
else if (dtMonth == 2) {
    var isleap = (dtYear % 4 == 0 && (dtYear % 100 != 0 || dtYear % 400 == 0));
    if (dtDay > 29 || (dtDay == 29 && !isleap)) return false;
}
   return true;
}

问题根源

  1. 月份索引计算错误:
    正则里(mar)是第5个捕获组、(may)是第7个捕获组,但代码循环时用dtMonth = i - 3,导致:
    • 匹配mar时,i=5 → 5-3=2(被当成2月,2月无31天,直接判无效)
    • 匹配may时,i=7 →7-3=4(被当成4月,4月只有30天,判无效)
  2. 年份索引错误:正则最后一个年份分组是第16个,但代码取了dtArray[17],会得到undefined,转成数字后为NaN,导致闰年判断逻辑失效。
  3. 正则冗余空选项:非捕获组里的?:|允许月份为空,不符合DD-MON-YY格式要求,还干扰分组逻辑。

修复方案

方案1:用映射表简化月份判断(推荐)

直接通过月份字符串映射到对应数字,避免分组索引出错:

function isdateField1(currVal) {
    if (currVal === '') return false;

    // 简化正则,去掉空选项,结构更清晰
    const rxDatePattern = /^(\d{1,2})-(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)-(\d{2})$/i;
    const dtArray = currVal.match(rxDatePattern);
    
    if (!dtArray) return false;

    const dtDay = parseInt(dtArray[1]);
    const dtYear = parseInt(dtArray[3]);
    // 月份字符串转数字
    const monthMap = {
        jan: 1, feb: 2, mar: 3, apr:4, may:5, jun:6,
        jul:7, aug:8, sep:9, oct:10, nov:11, dec:12
    };
    const dtMonth = monthMap[dtArray[2].toLowerCase()];

    // 边界校验
    if (dtMonth < 1 || dtMonth > 12) return false;
    if (dtDay < 1 || dtDay > 31) return false;
    // 小月31天校验
    if ([4,6,9,11].includes(dtMonth) && dtDay === 31) return false;
    // 二月特殊处理
    if (dtMonth === 2) {
        // 可选:两位年份转四位,比如99→1999,05→2005
        // const fullYear = dtYear + (dtYear > 50 ? 1900 : 2000);
        // const isleap = (fullYear % 4 === 0 && (fullYear % 100 !== 0 || fullYear % 400 === 0));
        const isleap = (dtYear % 4 === 0 && (dtYear % 100 !== 0 || dtYear % 400 === 0));
        if (dtDay > 29 || (dtDay === 29 && !isleap)) return false;
    }
    return true;
}

方案2:修正原代码的索引逻辑

如果要保留原正则结构,只需调整索引计算:

function isdateField1(currVal) {
    if (currVal === '') return false;

    var rxDatePattern = /^(\d{1,2})(-)(?:|(jan)|(feb)|(mar)|(apr)|(may)|(jun)|(jul)|(aug)|(sep)|(oct)|(nov)|(dec))(-)(\d{2})$/i;
    var dtArray = currVal.match(rxDatePattern);

    if (!dtArray) return false;

    var dtDay = parseInt(dtArray[1]);
    var dtMonth = parseInt(dtArray[3]);
    // 修正年份索引为16
    var dtYear = parseInt(dtArray[16]);

    if (isNaN(dtMonth)) {
        // 从分组3(jan)开始循环,到分组14(dec)结束
        for (var i = 3; i <= 14; i++) {
            if (dtArray[i]) {
                // 分组3对应1月,所以用i-2计算月份
                dtMonth = i - 2;
                break;
            }
        }
    }
    if (dtMonth < 1 || dtMonth > 12) return false;
    else if (dtDay < 1 || dtDay > 31) return false;
    else if ((dtMonth == 4 || dtMonth == 6 || dtMonth == 9 || dtMonth == 11) && dtDay == 31) return false;
    else if (dtMonth == 2) {
        var isleap = (dtYear % 4 == 0 && (dtYear % 100 != 0 || dtYear % 400 == 0));
        if (dtDay > 29 || (dtDay == 29 && !isleap)) return false;
    }
    return true;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 10:20:42