Треки
/
JavaScript
JavaScript
/
Вправи
/
Час зустрічі
Час зустрічі

Час зустрічі

Навчальна вправа

Вступ

У JavaScript є вбудований обʼєкт Date, який зберігає дату й час і надає методи для роботи з ними.

Caution

Він був заснований на класі java.util.Date з Java, який замінили на початку 2010-х років, але задля зворотної сумісності Date у JavaScript залишається.

Через те, як складно працювати з датами загалом, і через те, що обробка часових поясів або погана, або її зовсім немає, існує чимало бібліотек, як-от moment.js, day.js, date-fns і luxon. Жодної з них немає на Exercism.

У власних проєктах не використовуйте застарілий чи непідтримуваний пакунок на кшталт moment.js, а покладайтеся на сучасніші альтернативи, як-от luxon, або на ще не поширений Temporal. Ця вправа зосереджена на Date, який залишатиметься актуальним до самого кінця JavaScript.

Створення

Обʼєкт Date - це екземпляр класу Date. Його можна створити, не передаючи у функцію-конструктор жодних аргументів. У результаті отримуємо обʼєкт Date, який представляє поточну дату й час:

const now = new Date();
// => Thu Apr 14 2022 11:46:08 GMT+0530 (India Standard Time)
// Shows current day, date and time (in your time zone).

Мітка часу Unix (число)

Якщо передати число, його буде інтерпретовано як timestamp. Мітка часу - це ціле число, яке показує кількість мілісекунд, що минули з 1 січня 1970 UTC+0.

const epoch = new Date(0);
// Thu Jan 01 1970 01:00:00 GMT+0100 (Central European Standard Time)

const another = new Date(1749508766627);
// Tue Jun 10 2025 00:39:26 GMT+0200 (Central European Summer Time)

Можна було б очікувати, що new Date(0) створить «найраніший» обʼєкт дати, але JavaScript переводить дату в місцевий часовий пояс, тож насправді значення початку відліку Unix отримають лише ті, хто перебуває в часовому поясі GMT / з UTC+0.

Мітка часу ISO 8601 (рядок тексту, англ. string)

У конструктор Date можна передати значення-рядок тексту, яке представляє дату. Єдиний формат, який однаково працює в усіх реалізаціях, - це спрощена версія міжнародно визнаних і стандартизованих так званих рядків міток часу ISO 8601.

Момент часу за UTC має такий вигляд:

YYYY-MM-DDTHH:mm:ss.mssZ
YYYYMMDDTHHmmss.mssZ

де відбуваються такі підстановки:

Ключ Опис Типове значення
YYYY Календарний рік, записаний 4 цифрами
MM Календарний місяць, записаний 2 цифрами 01
DD Календарний день, записаний 2 цифрами 01
T Сама літера T, що відокремлює дату від часу
HH Години за 24-годинним форматом, 2 цифри 00
mm Хвилини, 2 цифри 00
ss Секунди, 2 цифри 00
mss Мілісекунди, 3 цифри 000
Z Сама літера Z, або зсув +/-HH:mm

Сама літера Z вказує на UTC (без часового поясу, без переходу на літній час).

Оскільки для більшості компонентів є типові значення, частини в кінці можна опускати:

YYYY-MM-DD

Типове значення: час 00:00:00.000

Якщо мітка часу не закінчується на Z і не закінчується на +HH:mm чи -HH:mm (що вказує на зсув часового поясу), то з історичних причин діє таке правило:

Якщо зсув часового поясу відсутній, форми лише з датою інтерпретуються як час UTC, а форми з датою й часом - як місцевий час. Тлумачення як часу UTC спричинене історичною помилкою у специфікації, яка суперечила ISO 8601, але її не можна було виправити через сумісність з вебом. Див. Broken Parser – A Web Reality Issue.

Caution

Інші формати, які приймає Date.parse, можуть працювати, а можуть і ні. Коли ми працюємо з датами в JavaScript, під час перетворення з string у Date завжди використовуймо мітку часу ISO 8601.

Форми лише з датою дозволені, але підтримуються не всі формати ISO 8601. Варто звернутися до сторінки з поясненням спрощеної версії на MDN.

Обʼєкт дати

Наявний обʼєкт дати теж можна використати як аргумент конструктора. Тоді створюється копія наявного обʼєкта Date з тією самою датою й часом.

const t1 = new Date();
const t2 = new Date(t1);
// Values of t1 and t2 will be the same.

Передавання окремих значень компонентів дати й часу

Обʼєкт дати, який представляє лише дату, можна створити, передавши три числа. Обʼєкт дати, який представляє дату й час, можна створити, передавши шість чисел.

const date1 = new Date(95, 11, 17);
// Creates Date for Dec 17 1995 00:00 if your local timezone is equivalent to UTC.

const date2 = new Date(2013, 12, 5, 13, 24, 0);
// Creates Date for Jan 5 2014 13:24 if your local timezone is equivalent to UTC.

Друге значення - це month, яке починається з 0 для січня й сягає 11 для грудня.

Date.parse()

Можна натрапити на згадки про функцію розбору дат Date.parse або на посилання на неї. Оскільки для цієї функції існує лише кілька інваріантів (істин), а решта реалізації не специфікована (а отже, не є стандартною), користуватися нею не варто.

Доступ до компонентів Date

В обʼєктів дати є чимало методів, які повертають компоненти дати:

getFullYear(); // Get the year (4 digits)
getMonth(); // Get the month, from 0 to 11.
getDate(); // Get the day of month, from 1 to 31.
getHours(); // Get the hour in a 24 clock, from 0 to 23
getMinutes(); // Get the minutes, from 0 to 59
getSeconds(); // Get the seconds, from 0 to 59
getMilliseconds(); // Get the milliseconds, from 0 and 999
getDay(); // Get the day of week, from 0 (Sunday) to 6 (Saturday).

Для кожного з них є відповідний варіант із set (наприклад, setFullYear), який оновлює значення. Будь-яке значення, що виходить за межі, переходить до наступного компонента:

const date = new Date('2025-02-28T12:42:00Z');
// => Fri Feb 28 2025 13:42:00 GMT+0100 (Central European Standard Time)

date.setDate(29);
// there was no February 29th in 2025.

date.getDate();
// => 1

date.toString();
// => Sat Mar 01 2025 13:42:00 GMT+0100 (Central European Standard Time)

Для всіх методів є варіанти UTC, які ігнорують місцевий часовий пояс.

Перетворення з дати

В обʼєктів дати є метод getTime(), який повертає мітку часу UNIX у мілісекундах, тобто кількість мілісекунд від півночі 1 січня 1970 року за UTC. Крім того, є метод toISOString(), який перетворює обʼєкт дати на рядок тексту з міткою часу ISO 8601.

Порівняння дат

Оператори більше (>) і більше або дорівнює (>=), а також менше (<) і менше або дорівнює (<=) можна застосовувати безпосередньо між двома датами або між датою та числом. Це працює, тому що JavaScript намагається привести дату до примітивного значення.

Advanced

Коли виконується порівняння двох дат або дати й числа, JavaScript викликає [Symbol.toPrimitive]("number"), який усередині викликає date.valueOf(). Останній рівнозначний виклику date.getTime().

Якщо ми не хочемо покладатися на цю поведінку, спершу перетворімо дату на число за допомогою getTime().

Дати не можна порівнювати на рівність (== і ===), а ось результат .getTime() - можна.

Вказівки

У цій вправі ми попрацюємо над кількома функціями, щоб керувати зустрічами. Система зберігає все в рядках тексту (англ. string) у форматі ISO 8601, але люди користуються календарем не так. Щоб перетворювати один формат на інший, потрібні різні функції.

1. Створіть зустріч

Створіть зустріч через n днів від поточного моменту на поточний час. Функція приймає n днів і повертає час зустрічі через n днів від поточного моменту.

createAppointment(4, now);
// Given now is Sun Oct 05 2022 23:28:43 GMT+0600 (Bangladesh Standard Time)
// => Sun Oct 09 2022 23:28:43 GMT+0600 (Bangladesh Standard Time)

Якщо другий параметр now не використано, слід використати поточний час.

2. Перетворіть дату на мітку часу

Багато інструментів працюють лише з міжнародним стандартизованим форматом ISO 8601. Напишіть функцію getAppointmentTimestamp, яка приймає дату й повертає рядок тексту в цьому форматі.

const appointment = new Date(Date.UTC(2010, 6, 16, 12, 42, 0, 0));

getAppointmentTimestamp(appointment);
// => '2010-07-16T12:42:00.000Z'

3. Отримайте подробиці зустрічі

Мітки часу важко читати, і функція для отримання подробиць зустрічі має з цим допомогти. Функція getAppointmentDetails приймає мітку часу у форматі ISO 8601 і повертає рік, місяць, число, годину і хвилину.

getAppointmentDetails('2022-04-24T08:15:00.000');
// => { year: 2022, month: 3, date: 24, hour: 8, minute: 15 }

4. Оновіть зустріч із заданими опціями

Функція отримає першим аргументом час зустрічі, а другим - обʼєкт із деякими опціями. Потрібно оновити зустріч відповідно до опцій в обʼєкті й повернути нову дату зустрічі. Обʼєкт опцій може містити кілька опцій.

updateAppointment('2022-02-09T09:20:00.000', { month: 6 });
// => { year: 2022, month: 6, date: 9, hour: 10, minute: 20 }

5. Отримайте час між двома зустрічами

Функція отримає два аргументи - дві зустрічі (мітки часу). Потрібно повернути різницю між цими моментами в секундах.

Оскільки пів секунди майже нічого не значить, округліть число перед тим, як його повернути.

timeBetween('2022-12-12T09:20:00.000', '2022-12-18T08:30:00.000');
// => 515400

6. Перевірте, чи зустріч на цей момент дійсна

Нарешті, коли зустріч призначено, система має перевірити, чи вона дійсна. Іншими словами, зустріч має бути в майбутньому, а не в минулому.

Напишіть функцію isValid, яка приймає два аргументи: мітку часу зустрічі (рядок тексту) і поточний час як мітку часу (рядок тексту), і повертає true, якщо зустріч відбувається в майбутньому відносно поточного часу.

isValid('2022-02-11T23:00:00.000', '2022-02-08T23:00:00.000');
// => true
Редагувати через GitHub Посилання відкривається в новому вікні або вкладці
JavaScript Exercism

Час розпочати Час зустрічі?

Зареєструйтеся на Exercism, щоб вивчати й опановувати JavaScript, а також 37 концепцій159 вправ та справжнє наставництво від людей, і все це безкоштовно.