原文 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
這種簡寫的日期格式也沒有考慮在內
感興趣的朋友可以發揮下,豐富下我們的轉換方法。