JS Regular Format Date and Time Automatically Fill 0
Tags: javascript, webdev, programming
Published: 2021-12-08 05:32:51


## Question

We often encounter development tasks with time and date formatting, and there are also many tool conversion methods. For example, you need to convert the date format `2022-3-4` to `2022-03-04`, That is, the single-digit month or day date is automatically prefixed with 0. It is also very easy to do it with the APIs of the third-party libraries of `moment.js` or `dayjs`. Let's take a look at the implementation by ourselves.

## Solution One

**Analysis:**

Let's take a look at the conventional plan first. Take this `2022-3-4` date as an example. We first split the string according to `-` to get an array, and then identify the single-digit dates of `3` and `4` respectively, `<10 `Put 0 in front, otherwise do not operate.

**Code:**

```js
function formatDate(str) {
  // Split according to - symbol
  return str
    .split("-")
    .map((item) => {
      // +item convert item string to number
      // Complete a prefix 0 when it is less than 10
      if (+item < 10) {
        return "0" + +item;
      }

      // No need to add 0 when it is greater than 10
      return item;
    })
    .join("-"); // Finally regroup back
}

// test
formatDate("2022-03-4"); // output '2022-03-04'
```

The above function only adapts to the simple conversion of `2022-3-4` to `2022-03-04`, more complex date format or date and time format, such as `2022-3-4 1:2: 3` can't match yet.
Moreover, we only recognize the format of `-` here. What if there are still `2022/3/4` and `2022.3.4`?

## Solution Two

**Analysis:**

Let's take a look at using regular expressions. Using regular expressions can not only simplify the code, but also make it easier to be compatible with more situations.

Our core idea is to use `Lookahead assertion` and `Lookbehind assertion` to identify the number in the middle of the date connection symbol, and then determine whether the number needs to be filled with 0. Before coding, let's get familiar with the usage of a few regular expressions.

1. `Lookahead assertion`:`(?=)`, and `Lookbehind assertion`:`(?<=)`,

   To understand simply, it is

   ```js
   // Lookahead assertion:
   A(?=B) //Find the A before B

   // Lookbehind assertion:
   (?<=B)A //Find the A behind B

   // Negative lookahead assertion:
   A(?!B) //Find A that is not B behind

   // Negative lookbehind assertion:
   (?<!B)A //Find A that is not B before
   ```

   We can use it here to identify the numbers between characters such as `-`, `/`, and `.`

2. Word boundary: `\b`

   - Words refer to the characters that `\w` can match, namely numbers, uppercase and lowercase letters, and underscores `[0-9a-zA-Z_]`
   - Boundary refers to the position of the gap between the left and right characters

   Here we can use it to identify the number from `-` to the begin or end of the date. For example, in `2022-3-4 1:2:5`, the gap after `4`, the gap before `1`, and the gap after `5` are all word boundaries.

3. The `replace` method replaces the matched string: `$&`.

   After the single digit number is matched, 0 must be added. `$&` means the matched number, and 0 can be added by using `0$&`.

**Code:**

```js
// Use $& to match
function formatDate(str) {
  /*
        replace the first parameter regular

        (?<=\/|-|\.|:|\b)\d{1} is Lookbehind assertion, find / or - or . or : or word boundary or a number after T

        \d{1}(?=\/|-|\.|:|\b) is Lookahead assertion, find / or - or . or : or word boundary or a number before T

        replace the string matched by the second parameter "0$&" is prefixed with 0

    */
  return str.replace(/(?<=\/|-|\.|:|\b|T)\d{1}(?=\/|-|\.|:|\b|T)/g, "0$&");
}

// Use $1 to match
function formatDate(str) {
  /*
        The regular of the first parameter of replace is the same as above
        
        replace the second parameter is a function, and the first input parameter is the first parameter matched. You can add 0 in the function.
    */
  return str.replace(
    /(?<=\/|-|\.|:|\b|T)\d{1}(?=\/|-|\.|:|\b|T)/g,
    function ($1) {
      return "0" + $1;
    }
  );
}

// test
formatDate("2022-3-4 1:2:3"); // output '2022-03-04 01:02:03'
formatDate("2022/3/4"); // output '2022/03/04'
formatDate("2022.3.4"); // output '2022.03.04'
formatDate("2020/8/9T1:2:3"); // output '2020/08/09T01:02:03'
```

## Conclusion

We just did the conversion of ordinary strings here, and there are some shortcomings

1. There is no built-in date check
2. Date format similar to `01/10/07` is not taken into consideration

Interested friends can play and enrich our conversion methods.Check my website: https://lwebapp.com/

## Reference
- [Original: JS Regular Format Date and Time Automatically Fill 0](https://lwebapp.com/en/post/format-date-time-add-zero)
- [String.prototype.replace()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace)
- [Assertions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Assertions#other_assertions)