HTMLとJQueryで、業務システム的な「数値入力→yyyy/MM/dd形式に変換」する日付入力テキストフィールドを実装

記事イメージ

HTML5では、日付入力フォームとしてinputタグのtype属性をdateにすることで、カレンダー(ピッカー)から日付を入力できるフォームがデフォルトで利用できます。

type="date"の見本

ただ、例えば業務システムなど同じ人が繰り返し使用するようなアプリ用途では、カレンダー入力よりも、数値で日付をサクサク入力できた方が便利なので、この形式はやや不便です。(OSやブラウザー、バージョン等で見え方が異なるというデメリットも。)

そこで今回は、次のように数値入力をすると、フォーカスアウト時に入力数値を日付形式に自動変換するテキストフィールド(入力窓)を、HTMLとJQueryで作成します。

想定する入力と、フォーカスアウト時に変換される結果(2022年5月に入力した場合)
  • 1 → 2022/05/01
  • 21 → 2022/05/211
  • 0225 → 2022/02/25
  • 20210521 → 2021/05/21
  • 123 → 2022/01/23
  • 2021/12/25 → 2021/12/25
  • あああ → (空欄にしてエラーメッセージを表示)

デモページをこちらに展示しています。

完成イメージ
完成イメージ

HTML

HTMLは、inputタグに属性をtext属性を指定してテキストフィールド(入力窓)を設置します。

指定したクラスに対してJQueryのセレクターをフックさせます。

HTML
<input type="text" class="sakai-date" style="margin: 50px;">

JavaScript・JQueryの実装

まずはJQueryを忘れずにインポートしましょう。

HTML
<!--JQueryをインポート-->
<script type="text/javascript" src="https://code.jquery.com/jquery-3.6.0.min.js" ></script>

ついで、テキストフィールドの入力終了イベントを、on関数(イベント種類はchange)で捕捉し、入力値を変換・置換する処理を実行します。

JavaScript
$(function() {
    $(document).on('change', '.sakai-date', function() {
        //入力値を取得
        let val = $(this).val();
        //入力値を日付テキストに変換
        let text = to_date_text(val); //to_date_text関数は、次のセクションで記述します。
        $(this).val(text);

        //エラーメッセージを表示
        if (text === undefined) {
            date_convert_error_msg($(this));  //date_convert_error_msg関数は、次のセクションで記述します。
        }
    });
})

上記コードで使用した、to_date_text関数(数値テキストからyyyy/MM/dd形式に変換する関数)と、date_convert_error_msg関数(テキストフィールドの下にエラーメッセージを表示)を実装します。

JavaScript
//数値テキストからyyyy/MM/dd形式に変換する関数
function to_date_text(str) {

    //入力値が意図するymd値を推論する処理
    if (str.indexOf('/') !== -1 || str.indexOf('-') !== -1) {
        //日付形式で入力された場合

        if (str.length >= 6) {
            //入力値が2022/5/1形式のケース
            
            //日付として正しいかの判定
            let date = new Date(str);
            if (!isNaN(date.getDate())) {
                var year = date.getFullYear();
                var month = date.getMonth() + 1;
                var day = date.getDate();
            }
        } else {
            //入力値が5/1形式のケース

            if (str.indexOf('/') !== -1) {
                var sp = str.split('/');
            } else if (str.indexOf('-') !== -1) {
                var sp = str.split('-');
            }
            var year = new Date().getFullYear();
            var month = sp[0];
            var day = sp[1];;
        }

    } else {
        //数値のみで入力された場合

        //全角数値を半角に変換
        str = str.replace(/[0-9]/g, function(s) {return String.fromCharCode(s.charCodeAt(0) - 0xFEE0)});
        //数値変換できない値であればフォームを空にして終了
        if (isNaN(str) || str === null || str === '') {
            return;
        }

        //文字列から年月日を推定
        if (str.length === 1 || str.length === 2) {
            //1~2文字の場合、年・月は現在時刻を使用
            var year = new Date().getFullYear();
            var month = new Date().getMonth() + 1;
            var day = parseFloat(str);
        } else if (str.length === 3) {
            //3文字の場合、年は現在時刻を使用
            var year = new Date().getFullYear();
            var month = parseFloat(str[0]);
            var day = parseFloat(str.substr(1, 2));
        } else if (str.length === 4) {
            //4文字の場合、年は現在時刻を使用
            var year = new Date().getFullYear();
            var month = parseFloat(str.substr(0, 2));
            var day = parseFloat(str.substr(2, 2));
        } else if (str.length === 8) {
            //8文字の場合
            var year = parseFloat(str.substr(0, 4));
            var month = parseFloat(str.substr(4, 2));
            var day = parseFloat(str.substr(6, 2));
        }
    }

    //ymd数値が日付として正しいか否かの判定→正しければ、フォーマットして返却
    let date_text = `${year}/${month}/${day}`;
    let date = new Date(date_text);
    if (isNaN(date.getDate())) {
        return;
    } else {
        return `${year}/${month <= 9 ? '0' : ''}${month}/${day <= 9 ? '0' : ''}${day}`;
    }
}

//エラー時にメッセージを表示
function date_convert_error_msg(dom) {
    let position = dom.position();
    //バルーンをHTMLに挿入
    $('body').append(`<div class="modal-msg-box" style="display: none; position: absolute; background-color: #888; color: #fff; border-radius: 6px; padding: 5px; top: ${position["top"] + 80}px; left: ${position["left"] + 30}px; max-width: 200px; max-height: 40px;"><span class="modal-msg-box-text">日付の形式が正しくありません。</span></div>`);
    //フェードイン・アウト処理
    let modal = $('.modal-msg-box');
    modal.fadeIn(500);
    setTimeout(() => { modal.fadeOut(500, () => modal.remove()) }, 2000);
}

完成形(HTML全体のコード)

以下の通りに完成しました。転用は自己責任の下でご自由にどうぞ。

デモページをこちらに展示しています。(再掲)

HTML
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8"/>
    <meta name="robots" content="noindex" />
    <title>テキスト→日付変換デモ | 堺docs</title>

    <!--JQueryをインポート-->
    <script type="text/javascript" src="https://code.jquery.com/jquery-3.6.0.min.js" ></script>

    <script type="text/javascript">
        $(function() {
            $(document).on('change', '.sakai-date', function() {
                //入力値を取得
                let val = $(this).val();
                //入力値を日付テキストに変換
                let text = to_date_text(val);
                $(this).val(text);

                //エラーメッセージを表示
                if (text === undefined) {
                    date_convert_error_msg($(this));
                }
            });
        })

        //エラー時にメッセージを表示
        function date_convert_error_msg(dom) {
            let position = dom.position();
            //バルーンをHTMLに挿入
            $('body').append(`<div class="modal-msg-box" style="display: none; position: absolute; background-color: #888; color: #fff; border-radius: 6px; padding: 5px; top: ${position["top"] + 80}px; left: ${position["left"] + 30}px; max-width: 200px; max-height: 40px;"><span class="modal-msg-box-text">日付の形式が正しくありません。</span></div>`);
            //フェードイン・アウト処理
            let modal = $('.modal-msg-box');
            modal.fadeIn(500);
            setTimeout(() => { modal.fadeOut(500, () => modal.remove()) }, 2000);
       }


        //数値テキストからyyyy/MM/dd形式に変換する関数
        function to_date_text(str) {

            //入力値が意図するymd値を推論する処理
            if (str.indexOf('/') !== -1 || str.indexOf('-') !== -1) {
                //日付形式で入力された場合

                if (str.length >= 6) {
                    //入力値が2022/5/1形式のケース
                    
                    //日付として正しいかの判定
                    let date = new Date(str);
                    if (!isNaN(date.getDate())) {
                        var year = date.getFullYear();
                        var month = date.getMonth() + 1;
                        var day = date.getDate();
                    }
                } else {
                    //入力値が5/1形式のケース

                    if (str.indexOf('/') !== -1) {
                        var sp = str.split('/');
                    } else if (str.indexOf('-') !== -1) {
                        var sp = str.split('-');
                    }
                    var year = new Date().getFullYear();
                    var month = sp[0];
                    var day = sp[1];;
                }

            } else {
                //数値のみで入力された場合

                //全角数値を半角に変換
                str = str.replace(/[0-9]/g, function(s) {return String.fromCharCode(s.charCodeAt(0) - 0xFEE0)});
                //数値変換できない値であればフォームを空にして終了
                if (isNaN(str) || str === null || str === '') {
                    return;
                }

                //文字列から年月日を推定
                if (str.length === 1 || str.length === 2) {
                    //1~2文字の場合、年・月は現在時刻を使用
                    var year = new Date().getFullYear();
                    var month = new Date().getMonth() + 1;
                    var day = parseFloat(str);
                } else if (str.length === 3) {
                    //3文字の場合、年は現在時刻を使用
                    var year = new Date().getFullYear();
                    var month = parseFloat(str[0]);
                    var day = parseFloat(str.substr(1, 2));
                } else if (str.length === 4) {
                    //4文字の場合、年は現在時刻を使用
                    var year = new Date().getFullYear();
                    var month = parseFloat(str.substr(0, 2));
                    var day = parseFloat(str.substr(2, 2));
                } else if (str.length === 8) {
                    //8文字の場合
                    var year = parseFloat(str.substr(0, 4));
                    var month = parseFloat(str.substr(4, 2));
                    var day = parseFloat(str.substr(6, 2));
                }
            }

            //ymd数値が日付として正しいか否かの判定→正しければ、フォーマットして返却
            let date_text = `${year}/${month}/${day}`;
            let date = new Date(date_text);
            if (isNaN(date.getDate())) {
                return;
            } else {
                return `${year}/${month <= 9 ? '0' : ''}${month}/${day <= 9 ? '0' : ''}${day}`;
            }
        }
    </script>
</head>
<body>
    値を入力すると、フォーカスアウト時に日付にフォーマットします。
    <br>
    <input type="text" class="sakai-date" style="margin: 50px;">
    <br>
    <input type="text" class="sakai-date" style="margin: 50px;">
</body>
</html>

記事筆者へのお問い合わせ、仕事のご依頼

当社では、IT活用をはじめ、業務効率化やM&A、管理会計など幅広い分野でコンサルティング事業・IT開発事業を行っております。

この記事をご覧になり、もし相談してみたい点などがあれば、ぜひ問い合わせフォームまでご連絡ください。

皆様のご投稿をお待ちしております。

記事筆者へ問い合わせする

※ご相談は無料でお受けいたします。
IT活用経営を実現する - 堺財経電算合同会社