<input type="date">
{{HTMLSidebar}}
Елементи <input>
з атрибутом type="date"
("тип=дата") створюють поля введення, що дають користувачеві можливість ввести дату: або за допомогою текстового поля, котре перевіряє відповідність введених даних, або особливого інтерфейсу вибору дати.
Значення результату включає рік, місяць та день, але не час. Типи поля введення time підтримує введення часу, а datetime-local – дати разом з часом.
Спробуйте його в дії
Користувацький інтерфейс введення в цілому відрізняється між браузерами; зверніться до Сумісності з браузерами по детальнішу інформацію. В непідтримуваних браузерах контрольний елемент зводиться до <input type="text">
.
Значення
Рядок, що представляє дату, введену в поле. Має формат згідно з ISO8601, він описаний у Форматі рядків дат.
Можна встановити усталене значення поля введення з датою всередині атрибута value
, ось так:
<input type="date" value="2017-06-01" />
Примітка: Показаний формат дати відрізнятиметься від реального
value
: показана дата форматується на основі локалі браузера користувача, однак розібранеvalue
завжди форматується відповідно доyyyy-mm-dd
.
Можна отримати та встановити значення дати за допомогою JavaScript, використовуючи властивості HTMLInputElement
value
та valueAsNumber
. Наприклад:
const dateControl = document.querySelector('input[type="date"]');
dateControl.value = "2017-06-01";
console.log(dateControl.value); // виводить "2017-06-01"
console.log(dateControl.valueAsNumber); // виводить 1496275200000, мітку часу JavaScript (у мілісекундах)
Цей код знаходить перший елемент <input>
, чий атрибут type
має значення date
, і встановлює його значенням 2017-06-01
(1 червня 2017 року). Потім він зчитує це значення назад у вигляді рядка та числа.
Додаткові атрибути
Атрибути, що є спільними для всіх елементів <input>
, застосовуються і до полів date
, але можуть не впливати на їх подання. Наприклад, size
та placeholder
можуть не працювати. Поля date
мають наступні додаткові атрибути.
max
Найпізніша прийнятна дата. Якщо value
, введене в елемент, пізніше, то елемент провалює валідацію обмежень. Якщо значення атрибута max
не є можливим рядком дати у форматі yyyy-mm-dd
, то елемент не має максимального значення дати.
Якщо встановлені й max
, і min
, то значення max
мусить бути рядком дати, що є пізнішою чи рівною тій, що в атрибуті min
.
min
Найраніша прийнятна дата. Якщо value
, введене в елемент, раніше, то елемент провалює валідацію обмежень. Якщо значення атрибута min
не є можливим рядком дати у форматі yyyy-mm-dd
, то елемент не має мінімального значення дати.
Якщо встановлені й max
, і min
, то значення min
мусить бути рядком дати, що є ранішою чи рівною тій, що в атрибуті max
.
step
Атрибут step
(крок) – число, що вказує відстань між поділками, до котрих має приставати значення, або особливе значення any
, описане нижче. Лише значення, рівні базі крокування (min
, якщо вказаний, інакше – value
, або ж відповідне усталене значення, якщо і цього немає), є дійсними.
Рядкове значення any
означає, що крокування не застосовується, тож дозволено будь-яке значення (враховуючи інші обмеження, наприклад, min
і max
).
Примітка: Коли дані, введені користувачем, не відповідають налаштуванням крокування, користувацький агент може заокруглити до найближчого дійсного значення, віддаючи перевагу числам у напрямку збільшення, коли є два рівновіддалені варіанти.
Для полів date
значення step
задається в днях, а працює – як число мілісекунд, рівне 86.400.000 разів по значення step
(воно зберігається й працює в мілісекундах). Усталене значення step
– 1, тобто 1 день.
Примітка: Якщо вказати
any
як значенняstep
, то для полівdate
це матиме такий само ефект, як1
.
Використання полів дати
Поля введення дати надають зручний інтерфейс вибору дат, а також нормалізують формат дати перед надсиланням на сервер, незалежно від локалі користувача.
В цьому розділі розглядатиметься просте та складніше використання <input type="date">
.
Базове використання полів дати
Найпростіше використання <input type="date">
залучає один <input>
разом із його <label>
, дивіться нижче:
<form action="https://example.com">
<label>
Введіть свій день народження:
<input type="date" name="bday" />
</label>
<p><button>Надіслати</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
>Оберіть бажану дату вечірки:
<input type="date" name="party" min="2017-04-01" max="2017-04-30" />
</label>
</form>
Наслідком є те, що можна обрати дні лише у квітні 2017 року: місяць та рік в текстовому полі не редагуються, і дати поза квітнем 2017 не можуть бути обрані у віджеті вибору.
Примітка: Ви повинні мати змогу використовувати атрибут
step
, щоб варіювати число днів, на котрі відбувається стрибок при інкременті (наприклад, щоб можна було вибрати лише суботи). Втім, схоже, що на час написання цього тексту це не у всіх реалізаціях так.
Контроль розміру поля введення
<input type="date">
не підтримує атрибути розміру форми, наприклад, size
. Віддавайте перевагу CSS для задання їм розмірів.
Валідація
Усталено <input type="date">
не перевіряє дійсність введеного значення, окрім його формату. Інтерфейси в загальному не дають ввести будь-що, що не є датою – що корисно – але можна залишити поле пустим чи, в тих браузерах, де поле введення виводиться як запасний варіант text
, ввести недійсну дату (штибу 32 квітня).
При використанні для обмеження доступних дат min
і max
(дивіться Встановлення максимальної та мінімальної дат) браузери, що це підтримують, покажуть помилку при спробі подати дату, що знаходиться поза межами. Втім, слід повторно перевірити подані результати, щоб пересвідчитися, що значення лежить в заданих межах, – на випадок, якщо вибір дати не повністю підтримується на пристрої користувача.
Також можна використати атрибут required
, щоб зробити введення дати обов'язковим: буде показана помилка, якщо спробувати подати пусте поле дати. Це повинно спрацювати в більшості браузерів, навіть якщо вони показують поле дати як текстове.
Погляньмо на приклад мінімальної та максимальної дат, де поле також є обов'язковим:
<form>
<label>
Оберіть бажану дату вечірки (обов'язково, між 1 та 20 квітня):
<input
type="date"
name="party"
min="2017-04-01"
max="2017-04-20"
required />
<span class="validity"></span>
</label>
<p>
<button>Надіслати</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 взагалі, надсилаючи дані напряму на ваш сервер. Якщо ваш сервер не зможе валідувати отримані дані, може статися лихо: дані можуть мати поганий формат, бути занадто великими, бути не того типу тощо.
Поводження з підтримкою браузерами
Браузери, що не підтримують такий тип поля, ввічливо відступають до текстового поля, але це створює проблему сталості користувацького інтерфейсу (представлені контрольні елементи відрізняються) та обробки даних.
Друга проблема – більш серйозна; при підтримці поля дати значення нормалізується до формату yyyy-mm-dd
. Однак із текстовим полем браузер не має уявлення, в якому форматі дата повинна бути, і є чимало форматів, у котрих люди записують дати. Наприклад:
ddmmyyyy
dd/mm/yyyy
mm/dd/yyyy
dd-mm-yyyy
mm-dd-yyyy
Month dd, yyyy
Одним способом це обійти є атрибут pattern
на полі дати. Навіть попри те, що віджет вибору дати його не використовуватиме, запасному текстовому полю такий атрибут знадобиться. Наприклад, спробуйте поглянути на наступне в браузері, що не підтримує поле дати:
<form>
<label
>Введіть дату свого народження:
<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). Звісно, це не зупинить людей від введення недійсних дат чи некоректних форматів. Тож проблема досі є.
Найкращий наразі спосіб роботи з даними у кросбраузерний спосіб – це або мати день, місяць та рік в окремих полях, або використовувати JavaScript-бібліотеку типу jQuery date picker.
Приклади
В цьому прикладі створюються два набори елементів користувацького інтерфейсу для вибору дат: нативний <input type="date">
та набір з трьох елементів <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>
<label for="day">День:</label>
<select id="day" name="day"></select>
</span>
<span>
<label for="month">Місяць:</label>
<select id="month" name="month">
<option selected value="January">Січень</option>
<option value="February">Лютий</option>
<option value="March">Березень</option>
<option value="April">Квітень</option>
<option value="May">Травень</option>
<option value="June">Червень</option>
<option value="July">Липень</option>
<option value="August">Серпень</option>
<option value="September">Вересень</option>
<option value="October">Жовтень</option>
<option value="November">Листопад</option>
<option value="December">Грудень</option>
</select>
</span>
<span>
<label for="year">Рік:</label>
<select id="year" name="year"></select>
</span>
</div>
</form>
Місяці – намертво вписані в код (вони завжди ті самі), а значення дня й року – динамічно генеруються залежно від обраних місяця й року, а також поточного року (дивіться коментарі коду нижче з детальними поясненнями, як ці функції працюють).
JavaScript
Інша частина коду, що може бути цікавою – визначення доступності функціональності: чи підтримує браузер <input type="date">
.
Створюється новий елемент <input>
element, потім його type
встановлюється в date
, потім негайно відбувається перевірка типу: браузери, що підтримують date
, повернуть text
, бо для типу date
запасним варіантом є тип text
. Якщо <input type="date">
не підтримується, то нативний віджет вибору ховається, а натомість показується запасний варіант – (<select>
).
// отримати віджети користувацького інтерфейсу
const nativePicker = document.querySelector(".nativeDatePicker");
const fallbackPicker = document.querySelector(".fallbackDatePicker");
const fallbackLabel = document.querySelector(".fallbackLabel");
const yearSelect = document.querySelector("#year");
const monthSelect = document.querySelector("#month");
const daySelect = document.querySelector("#day");
// спершу приховати запасний варіант
fallbackPicker.style.display = "none";
fallbackLabel.style.display = "none";
// перевірити, чи відступає поле дати до запасного текстового варіанту, чи ні
const test = document.createElement("input");
try {
test.type = "date";
} catch (e) {
console.log(e.message);
}
// якщо відступає, то виконати код всередині блока if () {}
if (test.type === "text") {
// приховати нативний віджет вибору та показати запасний варіант
nativePicker.style.display = "none";
fallbackPicker.style.display = "block";
fallbackLabel.style.display = "block";
// динамічно заповнити дні та роки
// (місяці завжди одні, тому – вписані в код)
populateDays(monthSelect.value);
populateYears();
}
function populateDays(month) {
// видалити поточний набір елементів <option> із меню
// <select> вибору дня, готуючи до встановлення нового набору
while (daySelect.firstChild) {
daySelect.removeChild(daySelect.firstChild);
}
// Створити змінну для зберігання нового числа днів до встановлення
let dayNum;
// 31 чи 30 днів?
if (
[
"January",
"March",
"May",
"July",
"August",
"October",
"December",
].includes(month)
) {
dayNum = 31;
} else if (["April", "June", "September", "November"].includes(month)) {
dayNum = 30;
} else {
// Якщо місяць – лютий, то перевірити, чи не є рік високосним
const year = yearSelect.value;
const isLeap = new Date(year, 1, 29).getMonth() === 1;
dayNum = isLeap ? 29 : 28;
}
// вставити коректне число нових елементів <option> в <select> дня
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, а потім
// обрали місяць, в котрому менше днів (наприклад, лютий),
// ця частина коду пересвідчується, що найпізніший доступний день
// є обраним, замість показувати пустий daySelect
if (daySelect.value === "") {
daySelect.value = previousDay - 1;
}
if (daySelect.value === "") {
daySelect.value = previousDay - 2;
}
if (daySelect.value === "") {
daySelect.value = previousDay - 3;
}
}
}
function populateYears() {
// отримати поточний рік як число
const date = new Date();
const year = date.getFullYear();
// Зробити цей рік, а також 100 років перед ним – доступними в меню <select> вибору року
for (let i = 0; i <= 100; i++) {
const option = document.createElement("option");
option.textContent = year - i;
yearSelect.appendChild(option);
}
}
// коли значення <select> місяця чи року міняються, перезапустити populateDays()
// на випадок того, що зміна вплинула на число доступних днів
yearSelect.onchange = () => {
populateDays(monthSelect.value);
};
monthSelect.onchange = () => {
populateDays(monthSelect.value);
};
//зберігати вибір дня
let previousDay;
// оновити те, який день був установленим раніше
// дивіться використання в кінці populateDays()
daySelect.onchange = () => {
previousDay = daySelect.value;
};
Примітка: Слід пам'ятати, що певні роки містять 53 тижні (дивіться Скільки тижнів у році (англ.))! Це слід враховувати при промисловій розробці застосунків.
Технічний підсумок
Значення | Рядок, що представляє дату в форматі YYYY-MM-DD, або є порожнім |
Події |
change та
input
|
Підтримувані загальні атрибути |
autocomplete ,
list ,
readonly і
step
|
Атрибути IDL |
list , value , valueAsDate ,
valueAsNumber .
|
Інтерфейс DOM | |
Методи |
select() ,
stepDown() ,
stepUp()
|
Неявна роль ARIA | немає відповідної ролі |
Специфікації
Специфікація |
---|
HTML Standard
(HTML)
# date-state-(type=date) |
Сумісність із браузерами
desktop | mobile | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
type="date"
|
Chrome Full support 20 | Edge Full support 12 | Firefox Full support 57 | Internet Explorer No support No | Opera Full support 11 | Safari Full support 14.1 | WebView Android Full support Yes | Chrome Android Full support Yes | Firefox for Android Full support 57 | Opera Android Full support 11 | Safari on iOS Full support 5 | Samsung Internet Full support Yes |
Додаткова інформація
- Загальний елемент
<input>
та інтерфейс для керування ним,HTMLInputElement
- Настанови з віджетів вибору дати й часу
- Вживані в HTML формати дати й часу
- Сумісність властивостей CSS