【问题标题】:Using regexp to validate a date using DD-Mon-YYYY format使用正则表达式验证使用 DD-Mon-YYYY 格式的日期
【发布时间】:2013-09-06 13:58:39
【问题描述】:

您好,我正在尝试以以下格式验证日期: 2011 年 3 月 3 日或 2007 年 12 月 12 日。我目前有一个在 3 个字符月份失败的正则表达式。我可能只需要对其进行调整以使其正常工作。

    //function isDate(txtDate) {
    function isDate(sender, args) {
        var currVal = document.getElementById('<%=txtChange_Date.ClientID%>').value;

            if (currVal == '')
                return false;

            //Declare Regex  
            var rxDatePattern = /^(\d{1,2})(\/|-)[a-zA-Z]{3}(\/|-)(\d{4})$/;

            var dtArray = currVal.match(rxDatePattern); // is format OK?

            if (dtArray == null)
                return false;

            //formerly //Checks for dd/mm/yyyy format.
            //Checks for dd-MMM-yyyy format.
            var dtDay = dtArray[1];
            var dtMonth = dtArray[3];
            var dtYear = dtArray[4];

            switch(dtMonth)
            {
                case 'Jan':
                    dtMonth = '01';
                    break;
                case 'Feb':
                    dtMonth = '02';
                    break;
                case 'Mar':
                    dtMonth = '03';
                    break;
                case 'Apr':
                    dtMonth = '04';
                    break;
                case 'May':
                    dtMonth = '05';
                    break;
                case 'Jun':
                    dtMonth = '06';
                    break;
                case 'Jul':
                    dtMonth = '07';
                    break;
                case 'Aug':
                    dtMonth = '08';
                    break;
                case 'Sep':
                    dtMonth = '09';
                    break;
                case 'Oct':
                    dtMonth = '10';
                    break;
                case 'Nov':
                    dtMonth = '11';
                    break;
                case 'Dec':
                    dtMonth = '12';
                    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;
        }

【问题讨论】:

  • 仅供参考的正则表达式与 jQuery 无关。我已经为你编辑了标题。
  • 有经过测试的 JS 日期验证脚本/库,可能值得一看。
  • 简单的答案是使用moment.js's isValid function

标签: javascript regex date


【解决方案1】:

您的代码有一些问题,但您的正则表达式没有问题,只是那个月份没有被分组。

其他变化

  • 转换月份的switch 需要将dtMonth 转换为小写,并且需要匹配大小写的case 语句。
  • 我使用parseInt 将日期部分显式转换为整数。我不知道这是dtDay 还是dtYear 的问题,但它导致了dtMonth 的问题。
  • 通过parseInt 更改,我添加了非数字检查和dtMonth
  • 我还将验证器移出事件处理程序。如果验证不是微不足道的,这只是一个很好的做法。

代码

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

    //Declare Regex  
    var rxDatePattern = /^(\d{1,2})(\/|-)([a-zA-Z]{3})(\/|-)(\d{4})$/;

    var dtArray = currVal.match(rxDatePattern); // is format OK?

    if (dtArray == null) return false;

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

    // need to change to lowerCase because switch is
    // case sensitive
    switch (dtMonth.toLowerCase()) {
        case 'jan':
            dtMonth = '01';
            break;
        case 'feb':
            dtMonth = '02';
            break;
        case 'mar':
            dtMonth = '03';
            break;
        case 'apr':
            dtMonth = '04';
            break;
        case 'may':
            dtMonth = '05';
            break;
        case 'jun':
            dtMonth = '06';
            break;
        case 'jul':
            dtMonth = '07';
            break;
        case 'aug':
            dtMonth = '08';
            break;
        case 'sep':
            dtMonth = '09';
            break;
        case 'oct':
            dtMonth = '10';
            break;
        case 'nov':
            dtMonth = '11';
            break;
        case 'dec':
            dtMonth = '12';
            break;
    }

    // convert date to number
    dtMonth = parseInt(dtMonth);

    if (isNaN(dtMonth)) return false;
    else 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;
}

jsFiddle

替代解决方案

您可能不喜欢真正复杂的正则表达式,但您可以通过处理正则表达式本身的切换来真正减少代码。以下通过将匹配组循环到未遇到未定义的组,然后将值偏移来获取匹配的月份。

function isDate(currVal) {

    if (currVal == '') return false;

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

jsFiddle

【讨论】:

    【解决方案2】:

    您的正则表达式没问题,您没有用括号括住月份子模式,因此您还没有定义捕获组。因此,您的 switch 语句失败:

    试试

    var rxDatePattern = /^(\d{1,2})(\/|-)([a-zA-Z]{3})(\/|-)(\d{4})$/;
    

    var dtYear = dtArray[5];  // now 5 instead of 4
    

    【讨论】:

      【解决方案3】:

      您需要围绕月份的括号来捕获它:

      /^(\d{1,2})(\/|-)([a-zA-Z]{3})(\/|-)(\d{4})$/
      

      这意味着您需要调整您当年的索引:

      var dtYear = dtArray[5];  // now 5 instead of 4
      

      【讨论】:

        【解决方案4】:

        看起来月份部分只是缺少括号,使其成为一个单独的组。

                /^(\d{1,2})(\/|-)([a-zA-Z]{3})(\/|-)(\d{4})$/
        
                var dtDay = dtArray[1];
                var dtMonth = dtArray[3];
                var dtYear = dtArray[5];
        

        【讨论】:

          【解决方案5】:

          这里是代码,不需要正则表达式和使用javascript构建日期解析。

          var isDate = (function() {
              var MONTHS = [
                  "Jan", 
                  "Feb", 
                  "Mar", 
                  "Apr", 
                  "May", 
                  "Jun", 
                  "Jul",
                  "Aug",
                  "Sep",
                  "Oct",
                  "Nov",
                  "Dec"
              ];
          
              return function (date) {
                  var v = new Date(date);
                  var day = v.getDate();
                  if(day < 10) {
                      day = "0" + day;
                  }
                  var month = MONTHS[v.getMonth()];
                  var year = v.getFullYear();
                  var total = day + "-" + month + "-" + year;
                  return date.toUpperCase() == total.toUpperCase();
              }
          }());
          

          THE FIDDLE

          【讨论】:

            猜你喜欢
            • 2013-11-15
            • 1970-01-01
            • 2012-01-03
            • 2019-07-18
            • 2011-11-02
            • 2020-02-03
            • 2020-04-09
            • 1970-01-01
            • 2023-04-07
            相关资源
            最近更新 更多