<input type="date">
<input>
要素の type="date"
入力型は、検証付きのテキストボックスまたは特殊な日付選択インターフェイスのどちらかで、ユーザーに日付を入力させる入力欄を生成します。
結果の値には年、月、日が含まれますが、時刻は含まれません。 time および datetime-local 入力型は時刻や日付と時刻の入力に対応しています。
The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone https://github.com/mdn/interactive-examples and send us a pull request.
入力欄のユーザーインターフェイスは、一般にブラウザーによってまちまちです。詳細はブラウザーの互換性を参照してください。対応していないブラウザーでは、このコントロールは単純な <input type="text"> に格下げされます。
日付を選択する専用のインターフェイスを持つブラウザーの中で、 Chrome や Opera のデータコントロールは次のように表示されます。
Edge の日付コントロールは次のように表示されます。
Firefox の日付コントロールは次のように表示されます。
値 | DOMString で、 YYYY-MM-DD 形式の日付、または空欄を表す |
イベント | change および input |
対応している共通属性 | autocomplete , list , readonly , step |
IDL 属性 | list , value , valueAsDate , valueAsNumber |
メソッド | select() , stepDown() , stepUp() |
値
入力欄に入力された日付を表す DOMString
です。日付は ISO8601 に従って書式化されており、これは HTML で使われる日付や時刻の形式の日付の文字列で説明されています。
次のように、日付の入力欄の既定値を value
属性に設定することができます。
<input type="date" value="2017-06-01">
表示される日付の書式は実際の value
とは異なります。 — 表示される日付はユーザーのブラウザーに設定されたロケールに基づいて書式になりますが、解釈された value
は常に yyyy-mm-dd
の書式です。
日付の値は JavaScript で入力要素の value
および valueAsNumber
プロパティを用いて、次のように取得したり設定したりすることができます。
var dateControl = document.querySelector('input[type="date"]');
dateControl.value = '2017-06-01';
console.log(dateControl.value); // "2017-06-01" と表示
console.log(dateControl.valueAsNumber); // 1496275200000 と UNIX タイムスタンプを表示
このコードは <input>
要素のうち type
が date
である最初のものを探し、値を 2017-06-01
(2017年6月1日) に設定します。それからその値を文字列と数字の書式で読み直しています。
追加の属性
すべての <input>
要素で共通する属性と共に、 date
型の入力欄は以下の属性にも対応しています。
属性 | 説明 |
---|---|
max |
受け付けられる最も遅い日付 |
min |
受け付けられる最も早い日付 |
step |
上下スピナーボタンで値を調整する時や、日付の検証の時の刻み間隔 |
max
受け付ける最も遅い日付です。要素に入力された value
がこれ以降になった場合、要素は制約検証に失敗します。 max
属性の値が yyyy-mm-dd
の書式のありうる日付ではない場合、要素は最大の日付値を持ちません。
max
と min
の両方の属性が設定された場合、この値は min
属性にあるものより遅いか、同じ日付文字列でなければなりません。
min
受け付ける最も早い日付です。要素に入力された value
がこれ以前になった場合、要素は制約検証に失敗します。 min
属性の値が yyyy-mm-dd
の書式のありうる日付でない場合、要素は最小の日付値を持ちません。
max
と min
の両方の属性が設定された場合、この値は max
属性で指定されたものより早いか、同じ日付を指定する必要があります。
step
step
属性は値が吸着する粒度を指定する数値、または後述する特殊な値 any
です。刻みの基準値に等しい値 (指定されていれば min
、そうでなければ value
、どちらも設定されていなければ適切な既定値) のみが妥当となります。
文字列値の any
は刻みがなく、どの値でも許可されることを意味します (min
や max
など、他の制約に制限されます)。
注: ユーザーがデータを入力したときには刻みの設定には吸着せず、ユーザーエージェントは直近の妥当な値、同じ距離の値の選択肢が二つあった場合は、正の方向の推奨値に丸められます。
date
入力欄では、 step
の値は日単位で指定します。また、 86,400,000 に step
を乗じた値に等しいミリ秒数として扱われます (数値はミリ秒単位であるため)。 step
の既定値は 1
であり、1日を表します。
any
を step
属性の値として指定すると、 1
を date
入力欄に設定したのと同じ効果になります。
date 入力欄の使用
日付入力は便利に見えます。 — 日付の選択に簡単なインターフェイスを提供し、サーバーに送信するデータの書式をユーザーのロケールに関係なく正規化してくれます。しかし、今のところブラウザーの対応が限定されているため、 <input type="date">
には問題があります。
この節では、 <input type="date">
の基本的な使い方と少し複雑な使い方を見てみてから、その後でブラウザーの互換性の問題を緩和するアドバイスを提供しましょう (ブラウザーの互換性の扱い を参照してください)。
今後ブラウザーの互換性がもっと普遍的になり、この問題が消滅することを願います。
日付入力の基本的な使用
もっとも単純な <input type="date">
の使用方法は、次のように基本的な <input>
と <label>
要素の組み合わせです。
<form action="https://example.com">
<label>
誕生日を入力してください。
<input type="date" name="bday">
</label>
<p><button>Submit</button></p>
</form>
この HTML は入力された日付を bday
キーに入れて https://example.com
に送ります。 — 結果の URL は https://example.com/?bday=1955-06-08
のようになります。
日付の最大値と最小値の設定
min
および max
属性を使用して、ユーザーが選択できる日付を制限することができます。次の例では、日付の最小値を 2017-04-01
に、日付の最大値を 2017-04-30
に設定しています。
<form>
<label for="party">希望するパーティーの日を選んでください。
<input type="date" name="party" min="2017-04-01" max="2017-04-30">
</label>
</form>
この結果は、2017年の4月の日付のみが選択できるようになります。 — テキストボックスの年と月の部分が編集できなくなり、日付選択ウィジェットで4月以外にスクロールすることができなくなります。
注: step
属性を使用すると、日付が加算するたびに飛ばす日数を設定できるはずです(例えば、土曜日のみを選択できるようにしたい場合など)。しかし、執筆時点でどの実装も正しく動作していないようです。
入力欄の寸法の制御
検証
既定で、 <input type="date">
は入力された値をその書式を超えて検証しません。インターフェイスは一般的に、日付でないものの入力をさせないからです。 — これは便利です。 — しかし、入力欄を空のままにしたり、 text
型にフォールバックするブラウザーにおいて、無効な日付を入力したりすることが可能です (例えば4月32日など)。
min
および max
を使用して有効な日付を制限すると (日付の最大値と最小値の設定を参照)、対応しているブラウザーは、範囲を外れたの日付を送信しようとしたときにエラーを表示するでしょう。しかし、ユーザーの端末が日付選択に完全に対応していない場合、値がこれらの日付の中にあることを保証するためには、送信された結果を再度チェックしなければならないでしょう。
required
属性を使用して、日付の入力を必須にすることもできます。 — 空の日付欄を送信しようとするとエラーが表示されるでしょう。これは、テキスト入力欄で代替されたとしても、ほとんどのブラウザーで動作するはずです。
日付の最小値と最大値の例と、入力欄を必須にする例を見てみましょう。
<form>
<label>
推奨したいパーティーの日を選択してください (必須、4月1日~20日):
<input type="date" name="party" min="2017-04-01" max="2017-04-20" required>
<span class="validity"></span>
</label>
<p>
<button>Submit</button>
</p>
</form>
不完全な日付 (または設定した範囲を外れた日付) を送信しようとすると、ブラウザーはエラーを表示します。例を実行してみましょう。
対応しているブラウザーで入力しなかった場合のスクリーンショットです。
上記の例で使用されている CSS です。 :valid
および :invalid
擬似要素を使用して、現在の値が妥当かどうかで入力欄の隣にアイコンを追加しています。アイコンは入力欄そのものではなく、入力欄の隣の <span>
に置くようにしないと、 Chrome ではコントロールの内側にコンテンツを生成するので、正しく整形したり表示したりすることができません。
label {
display: flex;
align-items: center;
}
span::after {
padding-left: 5px;
}
input:invalid + span::after {
content: '✖';
}
input:valid+span::after {
content: '✓';
}
重要: クライアント側のフォーム検証は、サーバー上の検証の代用にはなりません。誰かが HTML を改変したり、 HTML を完全にバイパスしてサーバーに直接データを送信したいrすることは簡単です。サーバーが受信したデータの検証に失敗した場合、不適切な形式のデータ、大きすぎるデータ、誤った種類のデータなどに遭遇すると、障害が発生するおそれがあります。
ブラウザーの対応の扱い
前述のように、現時点で日付入力を書く上で一番の問題はブラウザーの対応です。 Android 版 Firefox の日付選択はこの例のように表示されます。
対応していないブラウザーでは、文字列入力欄に安全に格下げされますが、これはユーザーインターフェイスの一貫性 (表示されるコントロールが異なること) とデータの扱い方の両方で問題を生みます。
2番目の問題はより深刻です。日付入力に対応していると、値が yyyy-mm-dd
の書式で正規化されます。しかし、文字列入力欄では、ブラウザーには日付がどの書式で入力されるかの認識がなく、また、以下のように人間が日付を書く書式は様々なものがあります。
ddmmyyyy
dd/mm/yyyy
mm/dd/yyyy
dd-mm-yyyy
mm-dd-yyyy
Month dd, yyyy
これを回避する方法の一つは、日付入力欄に pattern
属性を付けることです。日付選択ではこれを使用しませんが、文字列入力にフォールバックされたときには使用されます。例えば、次の例を未対応のブラウザーで見てみてください。
<form>
<label for="bday">誕生日を入力してください:
<input type="date" name="bday" required pattern="\d{4}-\d{2}-\d{2}">
<span class="validity"></span>
</label>
<p>
<button>送信</button>
</p>
</form>
送信ボタンを押すと、入力が ####-##-##
のパターン (#
は数字の0から9) に一致しない場合はエラーメッセージが表示され、入力欄が無効として強調表示されるのが分かるでしょう。もちろん、これでユーザーが無効な日付や不正な書式を入力するのを止めることはできません。ですから、まだ問題があります。
現時点では、ブラウザーに依存しない方法でフォームで日付を扱う最善の方法は、年月日を別々なコントロールに入力するようにするか、 jQuery date picker のような JavaScript ライブラリを使用することです。
例
この例では、日付を選択するユーザーインターフェイスの要素を2組作成します。ネイティブの <input type="date">
による選択と、ネイティブの日付入力に対応していない古いブラウザー向けの、3つの <select>
要素です。
HTML
HTML は次のようになります。
<form>
<div class="nativeDatePicker">
<label for="bday">誕生日を入力してください:</label>
<input type="date" id="bday" name="bday">
<span class="validity"></span>
</div>
<p class="fallbackLabel">誕生日を入力してください:</p>
<div class="fallbackDatePicker">
<span>
<select id="year" name="year">
</select>
<label for="year">年</label>
</span>
<span>
<select id="month" name="month">
<option selected>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
<option>6</option>
<option>7</option>
<option>8</option>
<option>9</option>
<option>10</option>
<option>11</option>
<option>12</option>
</select>
<label for="month">月</label>
</span>
<span>
<select id="day" name="day">
</select>
<label for="day">日</label>
</span>
</div>
</form>
月は (常に同じなので) ハードコーディングされていますが、年と日の値は、現在の年、および現在選択されている年と月によってそれぞれ動的に生成されます (どのように動作するかについての詳細な説明は、以下のコードのコメントを参照してください)。
JavaScript
もう一つの面白い部分は、機能の検出コードです。 — ブラウザーが <input type="date">
に対応しているかどうかを検出するためのものです。
新たな <input>
要素を生成し、その type
を date
に設定して、すぐにどの型になったのかをチェックします。対応していないブラウザーでは、 text
が返されます。これは、 date
型が text
型へフォールバックされるためです。 <input type="date">
に対応していない場合は、ネイティブの日付選択を非表示にして、フォールバック (<select>
) 表示します。
// 変数を定義
var nativePicker = document.querySelector('.nativeDatePicker');
var fallbackPicker = document.querySelector('.fallbackDatePicker');
var fallbackLabel = document.querySelector('.fallbackLabel');
var yearSelect = document.querySelector('#year');
var monthSelect = document.querySelector('#month');
var daySelect = document.querySelector('#day');
// 最初はフォールバックを隠す
fallbackPicker.style.display = 'none';
fallbackLabel.style.display = 'none';
// 新しい日付入力が文字列入力にフォールバックされるかどうか
var test = document.createElement('input');
try {
test.type = 'date';
} catch (e) {
console.log(e.description);
}
// もし文字列入力になるならば、 if() {} ブロックの中のコードを実行する
if(test.type === 'text') {
// ネイティブの日付選択を隠してフォールバック版を表示
nativePicker.style.display = 'none';
fallbackPicker.style.display = 'block';
fallbackLabel.style.display = 'block';
// 年と日を動的に生成する
// (月は常に同じなのでハードコーディング)
populateDays(monthSelect.value);
populateYears();
}
function populateDays(month) {
// delete the current set of <option> elements out of the
// day <select>, ready for the next set to be injected
while(daySelect.firstChild){
daySelect.removeChild(daySelect.firstChild);
}
// 挿入する日数を保持する変数を作成
var dayNum;
// 31日か30日か?
if(month === '1' | month === '3' | month === '5' | month === '7' | month === '8' | month === '10' | month === '12') {
dayNum = 31;
} else if(month === '4' | month === '6' | month === '9' | month === '11') {
dayNum = 30;
} else {
// 2月の場合は、閏年かどうかを計算する
var year = yearSelect.value;
var isLeap = new Date(year, 1, 29).getMonth() == 1;
isLeap ? dayNum = 29 : dayNum = 28;
}
// <select> に正しい数の新しい <option> 要素を挿入
for(i = 1; i <= dayNum; i++) {
var option = document.createElement('option');
option.textContent = i;
daySelect.appendChild(option);
}
// 前回の日が既に設定されていたら、 daySelect の値を
// 日に設定し、年を変えたときに1に戻ることを
// 避ける
if(previousDay) {
daySelect.value = previousDay;
// 前回設定されていた日が大きい数字、例えば31であり、
// その後で日数が少ない月 (例えば2月) を選択した場合、
// このコードで空欄の日選択を表示するのではなく、
// 利用可能な最大の日を選択するように保証する
if(daySelect.value === "") {
daySelect.value = previousDay - 1;
}
if(daySelect.value === "") {
daySelect.value = previousDay - 2;
}
if(daySelect.value === "") {
daySelect.value = previousDay - 3;
}
}
}
function populateYears() {
// 今年を数値として取得
var date = new Date();
var year = date.getFullYear();
// 今年から100年前までの年が <select> で選択できるようにする
for(var i = 0; i <= 100; i++) {
var option = document.createElement('option');
option.textContent = year-i;
yearSelect.appendChild(option);
}
}
// 年や月の <select> 値が変更されたら、 populateDays() を
// 再実行して日数を調整する
yearSelect.onchange = function() {
populateDays(monthSelect.value);
}
monthSelect.onchange = function() {
populateDays(monthSelect.value);
}
// 日の選択を保存
var previousDay;
// 以前どの日が設定されていたかを保存する
// 使い方は populateDays() を参照
daySelect.onchange = function() {
previousDay = daySelect.value;
}
注: 53週ある年もあることを忘れないでください (年あたりの週数を参照)。商品のアプリを開発するときはこれを念頭に置いておく必要があります。
仕様書
仕様書 | 状態 | 備考 |
---|---|---|
HTML Living Standard <input type="date"> の定義 |
現行の標準 | |
HTML5 <input type="date"> の定義 |
勧告 |
ブラウザーの互換性
BCD tables only load in the browser
関連情報
- 全般的な
<input>
およびその操作に使用するHTMLInputElement
インターフェイス - 日付と時刻の選択のチュートリアル
- HTML で使われる日付や時刻の形式
- CSS プロパティの互換性