原文 js正則格式化日期時間自動補0
背景
時間日期格式化的需求很常見,也有很多工具類轉換方法,比如需要將2022-3-4
這種日期格式轉化為2022-03-04
,也就是實現個位數月份或天數日期自動前置補 0。用moment.js
、dayjs
第三方庫的 API 也很容易做到,這里我們自己實現一下看看。
解法一
思路:
先來看看常規方案。就用這個2022-3-4
日期來舉例子,我們先根據-
切分字符串,得到一個數組,然后分別識別3
、4
這種個位數日期,<10
就前置補 0,否則不操作。
代碼:
function formatDate(str) {
// 根據 - 符號拆分
return str
.split("-")
.map((item) => {
// +item 將item字符串轉換為數字
// 小於10的時候就補全一個前綴0
if (+item < 10) {
return "0" + +item;
}
// 大於10的時候不用補0
return item;
})
.join("-"); // 最后重組回來
}
// 測試
formatDate("2022-03-4"); // 輸出 '2022-03-04'
上面這個方案,只適配了2022-3-4
轉2022-03-04
這種簡單的轉換,更復雜的日期格式或者日期時間格式,比如2022-3-4 1:2:3
還不能匹配到。
而且,我們這里只識別了-
這一種格式,假如還有2022/3/4
、2022.3.4
這種寫法呢?
解法二
思路:
再來看看用正則表達式,用正則表達式不僅可以簡化代碼,還能更容易的兼容更多情況。
我們的核心思路是用前瞻后顧來識別日期連接符號中間的數字,然后判斷數字是否需要補全 0。寫之前,先來熟悉幾個正則表達式的用法。
-
前瞻:
(?=)
,后顧:(?<=)
,簡單來理解,就是
// 前瞻: A(?=B) //查找B前面的A // 后顧: (?<=B)A //查找B后面的A // 負前瞻: A(?!B) //查找后面不是B的A // 負后顧: (?<!B)A //查找前面不是B的A
我們這里可以用來識別
-
、/
、.
等字符之間的數字 -
單詞邊界:
\b
- 單詞指的是
\w
可以匹配的字符,即數字、大小寫字母以及下划線[0-9a-zA-Z_]
- 邊界 指的是占位的字符左右的間隙位置
我們這里可以用於識別
-
到日期開始或結束位置的數字,比如2022-3-4 1:2:5
中,4
后面的間隙,1
前面的間隙,5
后面的間隙,都是單詞邊界 - 單詞指的是
-
replace
方法替換匹配的字符串:$&
。匹配到個位數數字之后,還要補 0,
$&
就是代表匹配到的數字,用0$&
就可以實現補 0。
代碼:
// 使用$&匹配
function formatDate(str) {
/*
replace第一個參數正則
(?<=\/|-|\.|:|\b)\d{1} 用的是后顧,查找 / 或者 - 或者 . 或者 : 或者 單詞邊界 或者 T 后面的一個數字
\d{1}(?=\/|-|\.|:|\b) 用的是前瞻,查找 / 或者 - 或者 . 或者 : 或者 單詞邊界 或者 T 前面的一個數字
replace 第二個參數"0$&" 匹配到的字符串前置補0
*/
return str.replace(/(?<=\/|-|\.|:|\b|T)\d{1}(?=\/|-|\.|:|\b|T)/g, "0$&");
}
// 使用$1匹配
function formatDate(str) {
/*
replace第一個參數正則和上面的一樣
replace 第二個參數是一個函數,第一個入參就是匹配到的第一個參數,可以在函數內處理補0
*/
return str.replace(
/(?<=\/|-|\.|:|\b|T)\d{1}(?=\/|-|\.|:|\b|T)/g,
function ($1) {
return "0" + $1;
}
);
}
// 測試
formatDate("2022-3-4 1:2:3"); // 輸出 '2022-03-04 01:02:03'
formatDate("2022/3/4"); // 輸出 '2022/03/04'
formatDate("2022.3.4"); // 輸出 '2022.03.04'
formatDate("2020/8/9T1:2:3"); // 輸出 '2020/08/09T01:02:03'
總結
我們這里只是做了普通字符串的轉換,也有些缺點
- 日期校驗沒有內置
- 類似
01/10/07
這種簡寫的日期格式也沒有考慮在內
感興趣的朋友可以發揮下,豐富下我們的轉換方法。