0から1までの段階で、出生日の正規表現を実現します.(JavaScript)


簡単に言うと
フォーム検証では、生年月日のチェックを正規表現で行うことが多いです.本論文では、出生日をいくつかの部分に分割し、段階的に出生日検査を実施する完全なプロセスを紹介している.本编の内容を理解した上で、正规表式をどのように编纂し、どのように応用するかについて、より一层の理解と理解があると思います.
声明:本稿の目的は、正規表現をどのように作成するかを説明するためのプロセスである.また、本明細書に関わるコードはすべて厳格なテストを受けていません.
私たちは1つの形式を、2018-06-15の生年月日のように、年と月と日付の3つの構成部分に分割し、それぞれの正則を作成します.
1年正則
最初に年正規表現の規則的な定義を与えます.
  • 年は4桁の数字からなる
  • です.
  • は19、20から始まる年
  • だけを受け入れます.
    上記の規則により、年の正規表現が書きやすいです.
    var pattern = /^(19|20)\d{2}$/;
    //   true
    console.log(pattern.test("2008"));
    / /の2つのスラッシュとその中間の文字は正規表現の直接量の定義である.^はマッチング文字列の先頭を表し、$はマッチング文字列の最後を表している.^(19|20)は19または20で始まる文字列にマッチすることを表し、小かっこのペアはいくつかの項目を一つのユニットに結合することである.\d{2}は、任意のASCIIデジタルに2回マッチすることを表し、\d[0-9]に相当し、{2}は前のエントリに2回マッチすることを示す.
    上記の正規表現は1900年から2099年までの年にマッチします.年の範囲を制限するには、次のようなルールが追加されます.
  • 年から1920年
  • 年に始まりました.
  • 年に2018年
  • で終了しました.
    以上の規則により、正規表現を変更すると以下のようになります.
    var pattern = /^(19[2-9]\d{1})|(20((0[0-9])|(1[0-8])))$/;
    //   false
    console.log(pattern.test("1916"));
    //   true
    console.log(pattern.test("2008"));
    //   false
    console.log(pattern.test("2022"));
    デモコード
    2月の法則
    最初に、月正規表現の規則的な定義を与えます.
  • 月は1-12
  • であることができます.
  • 月に1-9であれば、前に0
  • を追加できます.
    以上の規則に基づいて、下記の正則と簡単なテストを提供します.
    var pattern = /^((0?[1-9])|(1[0-2]))$/;
    //   false
    console.log(pattern.test("19"));
    //   true
    console.log(pattern.test("02"));
    //   true
    console.log(pattern.test("2"));
    //   true
    console.log(pattern.test("11"));
    デモコード
    3日付規則
    最初に日付正規表現の規則的な定義を与えます.
  • 日は、1-31
  • 日とすることができます.
  • 日付が1-9の場合、前に0
  • を追加することができます.
    以上の規則に基づいて、下記の正則と簡単なテストを提供します.
    var pattern = /^((0?[1-9])|([1-2][0-9])|30|31)$/;
    //   false
    console.log(pattern.test("32"));
    //   true
    console.log(pattern.test("02"));
    //   true
    console.log(pattern.test("2"));
    デモコード
    4グループ検証
    上記の年正則によると、月正則、日付正則を組み合わせて、生年月日の正規表現を作成します.
    var pattern = /^((19[2-9]\d{1})|(20((0[0-9])|(1[0-8]))))\-((0?[1-9])|(1[0-2]))\-((0?[1-9])|([1-2][0-9])|30|31)$/;
    //   true
    console.log(pattern.test("1923-3-18"));
    //   true
    console.log(pattern.test("1923-4-31"));
    //   true
    console.log(pattern.test("1923-2-29"));
    //   true
    console.log(pattern.test("2016-2-29"));
    デモコード
    以上のテスト結果から、上記の正則検証はまだ完全ではなく、主に2、4、6、9、11月の日数の問題が見られます.
    5完璧
    第4ステップの問題によって、追加限定ルールは以下の通りです.
  • 、6、9、11月31日がない
  • 月の平年は28日間です.
  • です.
  • 月閏年は29日で
  • 日です.
    平年閏年判定:
    4で割り切れる年は閏年で、4で割り切れない年は平年です.しかし、百年全体であれば、400によって割り引かれるしかない閏年です.そうでなければ、平年です.
    新規規則と説明に基づいて、以下の正則関数とテストを与えます.
    var checkBirth = function (val) {
        var pattern = /^((?:19[2-9]\d{1})|(?:20[01][0-8]))\-((?:0?[1-9])|(?:1[0-2]))\-((?:0?[1-9])|(?:[1-2][0-9])|30|31)$/;
        var result = val.match(pattern);
        if(result != null) {
            var iYear = parseInt(result[1]);
            var month = result[2];
            var date = result[3];
            if(/^((0?[469])|11)$/.test(month) && date == '31') {
                return false;
            } else if(parseInt(month)  == 2){
                if((iYear % 4 ==0 && iYear % 100 != 0) || (iYear % 400 == 0)) {
                    if(date == '29') {
                        return true;
                    }
                }
                if(parseInt(date) > 28) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }
    //   true
    console.log(checkBirth("1923-3-18"));
    //   false 4    31 
    console.log(checkBirth("1923-4-31"));
    //   false    
    console.log(checkBirth("1923-2-29"));
    //   true    
    console.log(checkBirth("2016-2-29"));
    デモコード
    上記の正規表現ではStringのmatch()法を用いており、この方法の唯一のパラメータは正規表現であり、整合結果からなる配列を返している.配列の最初の要素はマッチする文字列で、残りの要素は正規表現で括弧で囲まれたサブ表現です.一方、(:?...)は、このような形式は、単に一つのユニットに項目を組み合わせるだけであるが、そのグループに一致する文字は記憶されていない.この方法を利用して、後の順序で比較するために、正則マッチの順に、それぞれの年月日項目を取り出した.
    上記の分析とテストによって、私達は年月日の正則の一般的な判定を実現しただけでなく、期日範囲と2、4、6、9、11月などの特殊な月の日数の処理を実現しました.テスト結果は私達が設定した目標に達しました.
    6まとめ
    上記の分析と解説は正規表現を説明するためだけのものですので、上記のコードは製品環境には適用されません.ここで、比較的顕著な問題は、正規表現の濫用にあり、正則の強大さはモードに対する柔軟なマッチングにあるが、日付比較と検証の面ではDate()を用いるより直接的で簡便である.上記checkBirth()は肥大で複雑で、テストとメンテナンスコストが高いです.
    上記の関数を以下のように変更することを提案します.
  • 正則は基本的なフォーマットだけ判定します.
  • Date()日付範囲の判定をする
  • .
  • Date()は、月の対応する日数の検証を行う
  • .
    変更後の関数とデモンストレーションコードは以下の通りです.
    var checkBirth = function (val) {
        var pattern = /^(19|20)\d{2}\-((0?[1-9])|(1[0-2]))\-((0?[1-9])|([1-2]\d)|3[01])$/;
        if(pattern.test(val)) {
            var date = new Date(val);
            if(date < new Date("1919-12-31") || date > new Date()) {
                return false;
            }
            var month = val.substring(val.indexOf("-")+1,val.lastIndexOf("-"));
            return date && (date.getMonth()+1 == parseInt(month));
        }
        return false;
    }
    デモコード
    上記のコードは、分業が明確で、ロジックが簡単で、前のバージョンより大幅に向上しました.
    以上のように、正規表現は強力ですが、万能ではないので、正規表現を過剰に依存したり、乱用したりしないでください.