【问题标题】:Trying to validate date entry with javascript regex as the user types尝试在用户键入时使用 javascript 正则表达式验证日期输入
【发布时间】:2019-10-31 10:01:36
【问题描述】:

我正在尝试使用一些日期验证来更新旧应用,当用户在文本字段中键入它时。

我在这里有一个简单的演示 http://jsfiddle.net/7d82j0ky/2/ 如果你输入以下日期:

  • 05/24/1972(有效)
  • 2020 年 5 月 24 日(在这种情况下,年份无效,当前年份是我们最大的时间)
  • 05/32/1972(在这种情况下是无效日期)

正则表达式有效,但在您输入完整的日期格式 MM/DD/YYYY 之前它无效。如果您打开浏览器控制台,您会在输入时看到控制台输出消息。

我希望验证用户键入时,所以每个字符,如果有无效字符,我想阻止该无效字符的默认行为,因此永远不会添加它,所以:

  • 05/24 输入就可以了
  • 05/32 不行,通过阻止该键事件的默认行为,这两个不应出现在 UI 中,因此您在键入时只会在文本字段中看到“05/3”
  • 0a 不行,就像上面的“a”应该被阻止,这样您在输入时只会在文本字段中看到“0”。

在键入时匹配正则表达式的最佳方法是什么?

我在https://regex101.com/r/M8habw/1/ 有一些日期正则表达式的测试用例,根据我们在应用程序中关心的日期,它们似乎都运行良好。我不是非常擅长正则表达式,但这并不难。

这是满足在此处发布的 jsfiddle 代码:

<input class="input" type="text" maxlength="10" placeholder="MM/DD/YYYY"/>

$('.input').on('input', function(e) {
    var regex = /^(0[1-9]|1[0-2])\/(0[1-9]|1\d|2\d|3[01])\/((19[2-9]\d{1})|20[0|1]\d{1})$/g;

    if (!this.value.match(regex)) {
        console.log('nope');
        e.preventDefault();
    } else {
        console.log('yep');
    }
});

【问题讨论】:

  • 尝试var regex = /^(?:0[1-9]?|1[0-2]?)(?:\/(?:(?:0[1-9]?|1\d?|2\d?|3[01]?)(?:\/(?:1(?:9(?:[2-9]\d?)?)?|2(?:0(?:[01]\d?)?)?)?)?)?)?$/; 并与RegExp#test 一起使用:if (!regex.test(this.value)) {
  • 关于如何验证日期已经有很多问题了。正则表达式并不特别适合您正在尝试做的事情,其他方法更简单且更易于维护。此外,在获得月份和年份之前,您无法验证日期部分。
  • 我和@RobG 在一起。动态类型验证只会在用户完成输入之前抛出一堆错误——糟糕的用户体验。也许考虑使用一个日期选择器(比如来自 jQuery 的那个),然后在日期更改时进行验证。

标签: javascript jquery regex validation date


【解决方案1】:

您无法仅使用正则表达式验证日期。或者至少不是一个合理的。考虑到闰年等将是相当先进的。

不过,您可以使用更多的 javascript 来做到这一点。在您的 oninput 函数中,您可以去除非数字字符,使用您的数字字符串(确保它是正确的日期),然后只将其他字符(“格式化字符”)添加回它们应该在之后的位置。

如果您有一个格式为 MMDDYYYY 的部分日期(但可能只填写了一些字符)并且您希望确保这不会产生无效的日期,您可以使用如下所示的函数。
一个技巧是在 Javascript 中创建一个无效的日期并不总是会产生一个无效的结果,它只会溢出,所以2019-01-32 会给你2019-02-01 的日期。虽然在某些情况下很有用,但当我们试图检测无效日期时,这对我们来说很烦人。但是我们可以确保表示生成日期的字符串与我们提供的字符串相同。如果不同,我们就处于“溢出”的情况。

function hasErrors(val) {
    let month = val.slice(0, 2);
    let day = val.slice(2, 4);
    let year = val.slice(4);
    // The string is fully empty - not an invalid input
    if (!month.length) {
        return false;
    }
    // Only one of the months digits is filled out. Assume the rest will be filled out by the smallest possible valid value
    //   (optimistic heuristic)
    if (month.length === 1) {
        month += month === '0' ? '1' : '0';
    }
    // Invalid month
    if (+month > 12 || +month <= 0) {
        return true;
    }
    // Month valid but day not filled - ok
    if (!day.length) {
        return false;
    }
    // Only part of the day filled, same as above with the month
    if (day.length === 1) {
        day += day === '0' ? '1' : '0';
    }
    // Days always invalid
    if (+day > 31 || +day <= 0) {
        return true;
    }
    // If the year is not fully filled out, use any year with a 29 Feb
    if (year.length < 4) {
        year = '1972';
    }
    // Make sure the date is valid (e.g. no 31st of April)
    let sourceStr = [year, month, day].join('-');
    let date = new Date(sourceStr);
    if (!+date || date.toISOString().slice(0, 10) !== sourceStr) {
        return true;
    }

    // No error was detected
    return false;
}

这是example fiddle。

现在正如其他人所提到的,在 UX 方面,阻止用户输入是一个非常糟糕的主意。这使事情变得混乱,尤其是在尝试编辑字符串的中间而不是结尾时。更好的解决方案是通过样式来指示错误。这是一个example fiddle 没有阻止用户输入(只是更改了第 76 行附近的部分)。

【讨论】:

    猜你喜欢
    • 2016-02-26
    • 2019-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多