2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

日時系のinput要素に対し現在日時に基づく値を初期値として設定

Last updated at Posted at 2021-04-12

日時系のtypeのinput要素に対して、現在日時に基づく各typeに合った値を初期値として設定するスクリプトです。
対応するtypeはtime, date, datetime-local, month, week 及び text です。
初期値を設定したい要素のタグにdata-nowDateを追記することで初期値が設定されます。

sample
<input type='date' data-nowDate>

既に有効な値がvalueに設定済みの要素に対してはdata-nowDateを指定しても無視します。

ブラウザが対応していない日時系のtypeの場合は該当のtypeで本来設定されるvalue値を設定、その他の無効なtypeの場合はtextとして扱います。
typeがtextの場合は、data-nowDateに書式テンプレート文字を指定できます。

####テンプレート文字一覧####
%Y% 西暦 4桁
%Y2% 西暦 下2桁
%M% 月 2桁
%Ms% 月 0埋め無し
%D% 日 2桁
%Ds% 日 0埋め無し
%h% 時 2桁
%hs% 時 0埋め無し
%m% 分 2桁
%ms% 分 0埋め無し
%s% 秒 2桁
%ss% 秒 0埋め無し
%MS% ミリ秒 3桁
%MSs% ミリ秒 0埋め無し

sample
<input type='text' data-nowDate='%h%:%m%:%s%'>

###スクリプト###

input_date_default_set.js
'use strict';
{
    window.addEventListener('DOMContentLoaded', function() {
        const d = new Date();
        d.setMinutes(d.getMinutes() - d.getTimezoneOffset());

        const
            isoLocal = d.toISOString(),
            pos = {
                time            : [11, 16],
                date            : [ 0, 10],
                month           : [ 0,  7],
                'datetime-local': [ 0, 16],
            },
            elements = document.querySelectorAll('input[data-nowdate]');

        for(let i = 0; i < elements.length; i++) {
            const e = elements[i];
            if(e.value !== '') {
                continue;
            }
            const
                t = e.attributes.type !== undefined ?
                        e.attributes.type.value.toLowerCase() : 'text',
                type = e.type === t ?
                           t : (Object.keys(pos).indexOf(t) >= 0) ? t : 'text';

            if(Object.keys(pos).indexOf(type) >= 0) {
                const r = pos[type];
                e.value = isoLocal.slice(r[0], r[1]);
            }
            else if(type === 'week') {
                const
                    d_ = new Date(Math.floor((+d + 2592e5) / 6048e5) * 6048e5),
                    y  = d_.getUTCFullYear(),
                    w  = 1 + Math.floor((d_ - new Date(y + '-01-01T00:00:00Z')) / 6048e5);
                e.value = y + '-W' + ('0' + w).slice(-2);
            }
            else if(type === 'text') {
                const p = isoLocal.match(/\d+/g);
                if(e.dataset.nowdate.trim() === '') {
                    e.dataset.nowdate = '%Y%-%M%-%D% %h%:%m%:%s%';
                }
                e.value = e.dataset.nowdate
                    .replace(/%Y%/g,    p[0])           // %Y%  西暦 4桁
                    .replace(/%Y2%/g,   p[0].slice(-2)) // %Y2% 西暦 下2桁
                    .replace(/%M%/g,    p[1])           // %M%  月 2桁
                    .replace(/%Ms%/g,  +p[1])           // %Ms% 月 0埋め無し
                    .replace(/%D%/g,    p[2])           // %D%  日 2桁
                    .replace(/%Ds%/g,  +p[2])           // %Ds% 日 0埋め無し
                    .replace(/%h%/g,    p[3])           // %h%  時 2桁
                    .replace(/%hs%/g,  +p[3])           // %hs% 時 0埋め無し
                    .replace(/%m%/g,    p[4])           // %m%  分 2桁
                    .replace(/%ms%/g,  +p[4])           // %ms% 分 0埋め無し
                    .replace(/%s%/g,    p[5])           // %s%  秒 2桁
                    .replace(/%ss%/g,  +p[5])           // %ss% 秒 0埋め無し
                    .replace(/%MS%/g,   p[6])           // %MS% ミリ秒 3桁
                    .replace(/%MSs%/g, +p[6]);          // %MSs% ミリ秒 0埋め無し
            }
        }
    });
}

###サンプル###
動作デモ

index.html
<!DOCTYPE html>
<html lang='ja'>
<head>
    <meta name='viewport' content='width=device-width,initial-scale=1'>
    <meta charset='utf-8'>
    <title>日時系input要素に現在日時をデフォルト設定</title>
    <script src='input_date_default_set.js'></script>
</head>
<body>
    <!-- data-nowDateを追記で現在日時に基づく各typeに合った値を設定 -->
    time<br>
    <input type='time' data-nowDate><hr>
    date<br>
    <input type='date' data-nowDate><hr>
    datetime-local<br>
    <input type='datetime-local' data-nowDate><hr>
    month<br>
    <input type='month' data-nowDate><hr>
    week<br>
    <input type='week' data-nowDate><hr>

    text<br>
    <!-- type=textの場合に限り、data-nowDateに記入した書式テンプレートを反映 -->
    <input type='text' data-nowDate='%Y%-%M%-%D% %h%:%m%:%s%.%MS%'><br>
    &emsp;書式テンプレート<br>&emsp;%Y%-%M%-%D% %h%:%m%:%s%.%MS%<hr>
    <input type='text' data-nowDate='%Y2%-%Ms%-%Ds% %hs%:%ms%:%ss% %MSs%'><br>
    &emsp;書式テンプレート<br>&emsp;%Y2%-%Ms%-%Ds% %hs%:%ms%:%ss% %MSs%<hr>
    <!-- 書式テンプレート無指定時は %Y%-%M%-%D% %h%:%m%:%s% として解釈 -->
    <input type='text' data-nowDate><br>
    &emsp;書式テンプレートなし<hr>
</body>
</html>

**type='week'**の要素については、私が確認できる範囲では2021年4月の時点でUIも表示されとくに問題なく使用できそうだったのはWindows/MacOS/Android版のChromeくらいでした。
非対応typeでもtextとして扱われるならまだいいのですが、iOS(14.4.2)/iPadOS(14.4.2)に至っては、typeはweekを保ったまま初期値も設定できるにも関わらず、要素をタップしても専用UIが表示されることもなく内容を変更することができない(通常のソフトウェアキーボードは表示されるが値を変更できない)状態だったので、やむなく使用する際には他のtype以上に注意が必要かな、と感じました。

2
2
0

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
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?