2
0

More than 1 year has passed since last update.

【jQuery】日付自動生成型生年月日フォームを作る(うるう年判定含む)

Last updated at Posted at 2022-07-11

導入

問い合わせフォームや会員登録フォームで、生年月日を入力するプルダウン、よくありますよね。

その中で、月の末日というのは、「3月は31日まで」「9月は30日まで」「2月はうるう年なら29日まで」など、年月によって変わってきます。

存在しない日付は、最初から選択肢に無いほうが望ましいですよね。

ということで今回は、選択された「年月」から、選択可能な「日」を自動生成してくれる、さらにはうるう年も考慮にいれた、いい感じのフォームをjqueryで実装します。

1. フォームを作る

最初にシンプルなフォームを作ります。

<form action="./confirm.php" method="POST" enctype="multipart/form-data”>
         <table>
           <tr>
              <th>生年月日のフォーム</th>
              <td>
                <div class="flex-container">
                  <select id="year" name="year" class="field-year">
                  </select>
                  <label></label>
                  <select id="month" name="month" class="field-year">
                  </select>
                  <label></label>
                  <select id="day" name="day" class="field-year">
                  </select>
                  <label></label>
                </div>
              </td>
              </tr>
            <tr>
        </table>
<input type="submit" value="送信" class="btn btn-blue">
 </form>

セレクトボックスの中身は、以下のように<option>を一つずつ書くこともできますが、たとえば今回のように1970年から2022年だと、コードがとんでもなく長くなってしまいます。

<option value=“1970”>1970</option>
<option value=“1971”>1971</option>
<option value=“1972”>1972</option>

なので、選択肢を生成する関数を新たに作ります。

//年の選択肢生成
  var createYearOption = (startNum, endNum, current) => {
      let optionDom = '';
      for (let i = startNum; i <= endNum; i++) {
        if (i === current) { //現在年と合致する場合は初期値にする
          option = '<option value="' + i + '" selected>' + i + '</option>';
        } else {
          option = '<option value="' + i + '">' + i + '</option>';
        }
        optionDom += option;
      }
      $("#year").append(optionDom);
    }

optionの先頭と最後のvalue、現在の年を引数に取り、指定した個数分、<option>を生成します。
生成された<option>は、optionDomに追加されていき、最後の<option>まで追加されたら、セレクトボックスの中にinsertします。

同様に「月」と「日」の関数も作ります。

//月の選択肢生成
    var createMonthOption = (startNum, endNum, current) => {
      let optionDom = '';
      for (let i = startNum; i <= endNum; i++) {
        if (i === current) {
          option = '<option value="' + i + '" selected>' + i + '</option>';
        } else {
          option = '<option value="' + i + '">' + i + '</option>';
        }
        optionDom += option;
      }
      $("#month").append(optionDom);
    }

 //日の選択肢生成
    var createDayOption = (startNum, endNum, current) => {
      let optionDom = '';
      for (let i = startNum; i <= endNum; i++) {
        if (i === current) {
          option = '<option value="' + i + '" selected>' + i + '</option>';
        } else {
          option = '<option value="' + i + '">' + i + '</option>';
        }
        optionDom += option;
      }
      $("#day").append(optionDom);
    }

あとはこれをページに読み込むと同時に呼び出してあげます。
その前に現在日時も取得しておきましょう。
ちなみに、getMonth()に1を足しているのは、getMonth()の戻り値が、1月の場合は0、2月の場合は1というように、現在月-1の数値であるためです。

//今日の日付、年、月、日 を取得
    var today = new Date();
    var thisYear = today.getFullYear();
    var thisMonth = today.getMonth() + 1;
    var thisDate = today.getDate();
    var thisMonthDay = 31; 

//作った関数を呼び出す
   $(document).ready(function(){    
      createYearOption(1970,thisYear, thisYear);
      createMonthOption(1,12,thisMonth);
      createDayOption(1,thisMonthDay,thisDate);
    });

これでとりあえず、生年月日を選択できるセレクトボックスの完成です。

simple_form_image.png

しかし、このフォームには問題があります。
「2月30日」や「9月31日」などの存在しないであろう日付を選べてしまうのです。うるう年の影響も考慮しなくてはなりません。

2. うるう年判定関数を作る

次に、うるう年かどうかを判定する関数を作っておきます。
うるう年の定義は以下の通りです。

1.西暦年号が4で割り切れる
2.1の例外として、西暦年号が100で割り切れて400で割り切れない年は平年とする

これを踏まえて作った関数が以下になります。

//うるう年判定の関数
  function isLeapYear(year){
    if( (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) {
      return true;
    } else{
      return false;
    }
  }

はい、これで引数に数字を入れて、うるう年ならtrue、うるう年じゃないならfalseを返す関数ができました。

3. フォームに組み込む

年、または月が選択されたとき、それに対応する日数を判定する処理を作ります。

流れとしては、以下のような条件分岐で日数を判定し、それを先程作った、日付を生成してくれる関数createDayOption(1,thisMonthDay,thisDate);
のthisMonthDayに入れるといった感じです。

routing-map.png

$("#year").change(function(){  //年が選択されたとき
      var selected_year = $(this).val();       //現時点の年に入っている値を取得
      var selected_month = $('#month').val();  //現時点の月に入っている値を取得
      
      var month_days = [0,31,28,31,30,31,30,31,31,30,31,30,31];//各月の日数
      thisMonthDay = month_days[selected_month];
     
      if(selected_month == 2 && isLeapYear(selected_year) == true){  //うるう年かつ2月のとき
           thisMonthDay = 29;    
        } 

      $("#day").empty();
      createDayOption(1, thisMonthDay, 1);
    });

change()はselect要素の中身が変更された際にイベント処理を実行する関数なので、「年が選択されたとき」に処理が行われます。

同じように「月が選択されたとき」の処理も書きます。

$("#month").change(function(){  //月が選択されたとき
      var selected_year = $('#year').val();
      var selected_month = $(this).val();
      
      var month_days = [0,31,28,31,30,31,30,31,31,30,31,30,31];//各月の日数
      thisMonthDay = month_days[selected_month];

     if(selected_month == 2 && isLeapYear(selected_year) == true){  //うるう年かつ2月のとき
           thisMonthDay = 29;   
        } 

      $("#day").empty();
      createDayOption(1, thisMonthDay, 1);
    });

これで、年または月を選択すると、それに対応した日付の選択肢が反映される(うるう年も考慮された)セレクトボックスが完成しました!

LearYear.png

おわりに

いかがだったでしょうか。
思った以上に長いコードになってしまったので、リファクタリングの余地が大いにある気がしますが、個人的には今後フォームを作るときに迷わなくて済みそうです。
よかったら是非参考にしてみてください!

参考資料

みみぺんブログ:https://blog.mimipen.net/entry/2019/09/02/083834

2
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0