使用JavaScript巧妙地格式化时间

时间:2015-03-18 13:16:50

标签: javascript regex forms validation formatting

我需要帮助编写一个小正则表达式来将整数替换为文本输入字段中的时间格式字符串。

在我的表单中:我有一个文本输入字段,我应该写数字。当我写一个数字时:当输入字段失去焦点时,我想要一段JavaScript将其转换为人性化,可读的时间。使这个“聪明”的事情是,我希望能够尽可能少地编写:并将其转换为与我的数字相对应的最合适的时间。

让我举几个例子。如果我写:

7 it would resolve to 07:00
15 it would resolve to 15:00
93 it would resolve to 09:30
1945 it would resolve to 19:45
143 it would resolve to 14:30
... And so on ...

我想让它在输入字段失去焦点后进行此替换(onblur - 事件)

另外。我希望夜间有0前缀。像这样:

015 = 00:15
 03 = 00:30
012 = 00:12 
... And so on ...

我开始写if语句来做这件事,但我已经停止了我的轨道,因为我意识到需要这么多if语句,并且不会非常可靠。我觉得正则表达式会更加智能,因为它压缩了我的脚本并使加载时间更快。我掌握了正则表达式的基础知识,但我不知道如何为此目的编写一个聪明的表达式。

这是我的代码在我决定放弃它之前得到的:

var elem = document.getElementById("incidentHourStart-" + row);

if (elem.value.length === 1) {
    // Must be a whole hour (0-9)
} else if (elem.value.length === 2) {
    // Can be either two digits hour (10-23) or hour + whole minute (73: 07:30)
    if (parseInt(elem.value) >= 10 && parseInt(elem.value) <= 23) {
        // Two digits, whole hour (10-23)
    } else {
        // First digit is hour, and last one is whole minute (10, 20, 30, 40, 50)   
    }

} else if (elem.value.length === 3) {
    // First digit must be an hour value, middle digit is also hour if it is lower than 23, last digit is then always whole minutes
    if (parseInt(elem.value) >= 10 && parseInt(elem.value) <= 23) {
        // Two digits, whole hour (10-23)
    } else {
        // First digit is hour, and last one is whole minute (10, 20, 30, 40, 50)   
    }
} else if (elem.value.length === 4) {
    // First two digits must be an hour value, last digits is then fine selected minutes

}

如你所见:它看起来很丑陋!


更新

正如评论中所述:人们发现我的规则有点令人困惑。所以这是我希望它遵循的规则的伪代码。如果这可以巧妙地放入正则表达式:然后太棒了!如果不是:我会写出if/else块,或者按照建议将Regex分成几部分。

If text-length is equal to 1
    Resolve as whole hour between 0-9

    Examples:
        2 = 02:00
        8 = 08:00
        5 = 05:00

If text-length is equal to 2 AND number is between 10 and 23
    Resolve as whole hour between 10-23

    Examples:
        15 = 15:00
        11 = 11:00
        22 = 22:00

If text-length is equal to 2 AND number is NOT between 10 and 23
    Resolve as whole hour and minutes incremented by 10's (10, 20, 30, 40, 50)

    Examples:
        73 = 07:30
        24 = 02:40
        95 = 09:50

If text-length is equal to 3 AND first two numbers are between 10 and 23
    Resolve two first digits as hours and last digit as minutes incremented by 10's (10, 20, 30, 40, 50)

    Examples:
        133 = 13:30
        195 = 19:50
        111 = 11:10
        162 = 16:20

If text-length is equal to 3 AND first two numbers are NOT between 10 and 23
    Resolve first digit as whole hour, and last two as minutes.

    Examples:
        225 = 02:25
        922 = 09:22
        557 = 05:57
        451 = 04:51

If text-length is equal to 1 AND first digit is equal to 0
    Resolve as mid-night

    Example:
        0 = 00:00

If text-length is equal to 2 AND first digit is equal to 0
    Resolve as mid-night + minutes incremented by 10's (10, 20, 30, 40, 50)

    Examples:
        02 = 00:20
        05 = 00:50
        03 = 00:30

If text-length is equal to 3 AND first digit is equal to 0
    Resolve as mid-night + full minutes.

    Examples:
        024 = 00:24
        011 = 00:11
        056 = 00:56

If text-length is equal to 4
    Resolve as regular minutes and hours without the colon (:)

    Examples:
        1524 = 15:24
        2211 = 22:11

2 个答案:

答案 0 :(得分:1)

不要让自己比你需要的更难。简单的说;不要用一个正则表达式来做这件事。在使用RegEx之前,不要忘记修改输入。

首先检查零前缀,例如:

^0(\d+)$

然后,如果不匹配,请检查正常编号并将其与捕获组分开,但需要:

^([^0]\d{1,3})$ // Can do negative lookbehind here, but I left it simple in this case

正则表达式经常被滥用来解决一种模式中的更大问题。如果情况需要,拆分逻辑会好得多。不要过于复杂的代码。它会破坏后来需要阅读它的大脑。

答案 1 :(得分:0)

我找到了解决方案并将其部署了大约1.5个月。到目前为止:它很棒。我的同事喜欢这个功能,真的节省了很多时间!到目前为止:没有任何故障报告给我。

所以这就是我所做的:

我根据问题的评论中的建议,使用if/else块将我的伪代码重新编写为实际的JavaScript代码。我把它全部插入到我从输入字段上的onblur事件调用的函数中。像这样:

<input type="text" id="incidentHourStart-1" onblur="resolveTimeField(1);">

因此,只要输入字段失去焦点,就会发生格式化。

以下是我的功能:

function resolveTimeField(row) {
    var elem = document.getElementById("incidentHourStart-" + row);

    if (elem.value.length === 1) {

        // Must be a whole hour (0-9)
        elem.value = "0" + elem.value + ":00";

    } else if (elem.value.length === 2) {

        // Can be either two digits hour (10-23) or hour + whole minute (73: 07:30)
        if (parseInt(elem.value) >= 10 && parseInt(elem.value) <= 23) {
            // Two digits, whole hour (10-23)
            elem.value = elem.value + ":00";
        } else {
            // First digit is hour, and last one is whole minute (10, 20, 30, 40, 50)

            var hours = elem.value.substring(0, 1);
            var minutes = elem.value.substring(1, 2);
            elem.value = "0" + hours + ":" + minutes + "0";

        }
    } else if (elem.value.length === 3) {

        // First digit must be an hour value, middle digit is also hour if it is lower than 23, last digit is then always whole minutes
        var firstDigits = elem.value.substring(0, 2);

        if (parseInt(firstDigits) >= 10 && parseInt(firstDigits) <= 23) {

            // 3 digits, first two are hours, and last digit is minutes incremented by 10's
            var hours = elem.value.substring(0, 2);
            var minutes = elem.value.substring(2, 3);
            elem.value = hours + ":" + minutes + "0";

        } else {

            // First digit is hour, and last two is full minutes
            var hours = elem.value.substring(0, 1);
            var minutes = elem.value.substring(1, 3);
            elem.value = "0" + hours + ":" + minutes;

        }
    } else if (elem.value.length === 4) {

        // First two digits must be an hour value, last digits is then fine selected minutes
        var hours = elem.value.substring(0, 2);
        var minutes = elem.value.substring(2, 4);
        elem.value = hours + ":" + minutes;

    }
}

如果您想自行测试代码,可以使用JSFiddle

我的函数将一个参数引用为row。这是因为我正在使用的字段位于一个动态表中,可以让我的同事一次注册更多数据。

目前它没有任何形式的输入验证来检查插入的值是否有效。因此,您可以将999之类的内容写入字段,并将其解析为09:99。这对我们的环境来说不是一个关键特性,但我可以想象,如果需要它将很容易实现。如果我将来实施这样的验证功能,我会更新这篇文章。