简体   繁体   English

使用JavaScript进行巧妙的时间格式化

[英]Clever time formatting with JavaScript

I need help writing a little Regular Expression to replace integers into a time format string in a text input field. 我需要编写一些正则表达式以将整数替换为文本输入字段中的时间格式字符串的帮助。

In my form: I have a text input field where I'm supposed to write numbers. 在我的表单中:我有一个文本输入字段,应该在其中输入数字。 And when I write a number: I want a piece of JavaScript to convert it to a human-friendly, readable time when the input field loses focus. 当我写一个数字时:当输入字段失去焦点时,我想用一段JavaScript将其转换为对人类友好的可读时间。 The thing that makes this "Clever" is that I want to be able to write as little as absolutely possible: And have it transform to the most appropriate time corresponding to my number. 使这个“聪明”的一件事是,我希望能够尽可能地少写:并将其转换为与我的号码相对应的最合适的时间。

Let me give you a few examples. 让我举几个例子。 If I write: 如果我写:

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 ...

I want it to do this replacement after the input field loses focus ( onblur -event) 我希望它在输入字段失去焦点之后执行此替换( onblur -event)

Also. 也。 I want to have a 0 prefix for night hours. 我想在夜间设置0前缀。 Like this: 像这样:

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

I begun writing if statements to do this, but I stopped dead in my tracks because I realized it would take so many if statements, and would not be very reliable. 我开始编写if语句来执行此操作,但是我停滞不前,因为我意识到if语句会花费很多,而且不是很可靠。 I feel like Regular Expressions would be much smarter since it compacts my script and makes loading time quicker. 我觉得正则表达式会更聪明,因为它可以压缩脚本并缩短加载时间。 I grasp the basics of Regular Expressions, but I don't know how to write a clever one for this purpose. 我掌握了正则表达式的基础知识,但是我不知道如何为此编写一个聪明的表达式。

This is what my code got to before I decided to drop it: 这是我的代码决定删除之前要达到的目的:

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

}

As you can see: It looks very ugly! 如您所见:看起来非常难看!


UPDATE: 更新:

As stated in the comments: People have found my rules a little confusing. 如评论中所述:人们发现我的规则有些混乱。 So here is the pseudo code of rules I want it to follow. 所以这是我希望它遵循的规则的伪代码。 If this can be put into a Regex in a clever way: Then awesome! 如果可以巧妙地将其放入正则表达式中:太棒了! If not: I will write out the if/else blocks, or split the Regex up into parts as suggested. 如果不是:我将写出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

Don't make it harder on yourself than you need. 不要让自己变得比自己更难。 Simply put; 简单的说; don't do this in one regular expression. 不要在一个正则表达式中执行此操作。 Also don't forget to trim your input before using RegEx. 同样不要忘记在使用RegEx之前先修剪输入。

First of all check the zero-prefixed one, something like: 首先检查以零开头的前缀,例如:

^0(\d+)$

Then if that doesn't match, do the check for the normal numbering and split it with the capture groups however you want: 然后,如果不匹配,请检查常规编号,并根据需要将其与捕获组分开:

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

Regular expressions are often misused to solve a bigger problem in one pattern. 正则表达式经常被误用于以一种模式解决更大的问题。 It's much better to split logic if the situation asks for it. 如果情况需要,最好拆分逻辑。 Don't overcomplicate code. 不要使代码过于复杂。 It will break whoever needs to read it later's brain. 它将破坏以后需要阅读它的人的大脑。

I have found a solution and had it deployed for about 1.5 months now. 我找到了一个解决方案,并将其部署了大约1.5个月。 And so far: It works great. 到目前为止:效果很好。 My co-workers love this functionality, and really saves up a lot of time! 我的同事喜欢此功能,确实节省了很多时间! So far: No faults have been reported to me. 到目前为止:尚未向我报告任何错误。


So here is what I did: 所以这就是我所做的:

I bascially re-wrote my pseudo-code into actual JavaScript code using if/else blocks as suggested in the question's comments. 我基本上按照问题注释中的if/else块将伪代码重新编写为实际的JavaScript代码。 I stuck it all into a function that I call from an onblur event on the input fields. 我将其全部粘贴到我在输入字段上的onblur事件中调用的函数中。 Like this: 像这样:

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

So the formatting occurs as soon as the input field loses focus. 因此,一旦输入字段失去焦点,就会进行格式化。

Here is what my function looks like: 这是我的函数:

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;

    }
}

Here is a JSFiddle if you want to test out the code for yourself 如果您想自己测试代码,这是一个JSFiddle

My function takes one parameter referenced as row . 我的函数采用一个引用为row参数。 This is because the fields I am working with lays within a dynamic table that lets my co-workers register more data in one go. 这是因为我正在使用的字段位于一个动态表中,该动态表使我的同事可以一次性注册更多数据。

Currently it does not have any forms of input validation that checks if the inserted value is valid. 当前,它没有任何形式的输入验证来检查插入的值是否有效。 So you could write something like 999 into the field and have it resolve to 09:99 . 因此,您可以在字段中写入999之类的内容,并将其解析为09:99 This is not a critical feature for our environment, but I can imagine it would be fairly easy to implement shall it be required. 对于我们的环境来说,这不是关键特性,但是我可以想象,如果需要的话,实现起来会相当容易。 I will update this post if I ever implement such a validation feature in the future. 如果以后再实现这种验证功能,我将更新此帖子。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM